libv8 3.10.8.0 → 3.11.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (215) hide show
  1. data/Rakefile +10 -3
  2. data/ext/libv8/compiler.rb +46 -0
  3. data/ext/libv8/extconf.rb +5 -1
  4. data/ext/libv8/make.rb +13 -0
  5. data/lib/libv8/version.rb +1 -1
  6. data/patches/add-freebsd9-and-freebsd10-to-gyp-GetFlavor.patch +11 -0
  7. data/patches/src_platform-freebsd.cc.patch +10 -0
  8. data/vendor/v8/ChangeLog +124 -0
  9. data/vendor/v8/DEPS +27 -0
  10. data/vendor/v8/Makefile +7 -0
  11. data/vendor/v8/SConstruct +15 -2
  12. data/vendor/v8/build/common.gypi +129 -157
  13. data/vendor/v8/build/gyp_v8 +11 -25
  14. data/vendor/v8/build/standalone.gypi +9 -3
  15. data/vendor/v8/include/v8.h +5 -3
  16. data/vendor/v8/src/SConscript +1 -0
  17. data/vendor/v8/src/api.cc +4 -33
  18. data/vendor/v8/src/api.h +2 -2
  19. data/vendor/v8/src/arm/builtins-arm.cc +5 -4
  20. data/vendor/v8/src/arm/code-stubs-arm.cc +21 -14
  21. data/vendor/v8/src/arm/codegen-arm.cc +2 -2
  22. data/vendor/v8/src/arm/debug-arm.cc +3 -1
  23. data/vendor/v8/src/arm/full-codegen-arm.cc +3 -102
  24. data/vendor/v8/src/arm/ic-arm.cc +30 -33
  25. data/vendor/v8/src/arm/lithium-arm.cc +20 -7
  26. data/vendor/v8/src/arm/lithium-arm.h +10 -4
  27. data/vendor/v8/src/arm/lithium-codegen-arm.cc +106 -60
  28. data/vendor/v8/src/arm/macro-assembler-arm.cc +49 -39
  29. data/vendor/v8/src/arm/macro-assembler-arm.h +5 -4
  30. data/vendor/v8/src/arm/regexp-macro-assembler-arm.cc +115 -55
  31. data/vendor/v8/src/arm/regexp-macro-assembler-arm.h +7 -6
  32. data/vendor/v8/src/arm/simulator-arm.h +6 -6
  33. data/vendor/v8/src/arm/stub-cache-arm.cc +64 -19
  34. data/vendor/v8/src/array.js +7 -3
  35. data/vendor/v8/src/ast.cc +11 -6
  36. data/vendor/v8/src/bootstrapper.cc +9 -11
  37. data/vendor/v8/src/builtins.cc +61 -31
  38. data/vendor/v8/src/code-stubs.cc +23 -9
  39. data/vendor/v8/src/code-stubs.h +1 -0
  40. data/vendor/v8/src/codegen.h +3 -3
  41. data/vendor/v8/src/compiler.cc +1 -1
  42. data/vendor/v8/src/contexts.h +2 -18
  43. data/vendor/v8/src/d8.cc +94 -93
  44. data/vendor/v8/src/d8.h +1 -1
  45. data/vendor/v8/src/debug-agent.cc +3 -3
  46. data/vendor/v8/src/debug.cc +41 -1
  47. data/vendor/v8/src/debug.h +50 -0
  48. data/vendor/v8/src/elements-kind.cc +134 -0
  49. data/vendor/v8/src/elements-kind.h +210 -0
  50. data/vendor/v8/src/elements.cc +356 -190
  51. data/vendor/v8/src/elements.h +36 -28
  52. data/vendor/v8/src/factory.cc +44 -4
  53. data/vendor/v8/src/factory.h +11 -7
  54. data/vendor/v8/src/flag-definitions.h +3 -0
  55. data/vendor/v8/src/frames.h +3 -0
  56. data/vendor/v8/src/full-codegen.cc +2 -1
  57. data/vendor/v8/src/func-name-inferrer.h +2 -0
  58. data/vendor/v8/src/globals.h +3 -0
  59. data/vendor/v8/src/heap-inl.h +16 -4
  60. data/vendor/v8/src/heap.cc +38 -32
  61. data/vendor/v8/src/heap.h +3 -17
  62. data/vendor/v8/src/hydrogen-instructions.cc +28 -5
  63. data/vendor/v8/src/hydrogen-instructions.h +142 -44
  64. data/vendor/v8/src/hydrogen.cc +160 -55
  65. data/vendor/v8/src/hydrogen.h +2 -0
  66. data/vendor/v8/src/ia32/assembler-ia32.h +3 -0
  67. data/vendor/v8/src/ia32/builtins-ia32.cc +5 -4
  68. data/vendor/v8/src/ia32/code-stubs-ia32.cc +22 -16
  69. data/vendor/v8/src/ia32/codegen-ia32.cc +2 -2
  70. data/vendor/v8/src/ia32/debug-ia32.cc +29 -2
  71. data/vendor/v8/src/ia32/full-codegen-ia32.cc +8 -101
  72. data/vendor/v8/src/ia32/ic-ia32.cc +23 -19
  73. data/vendor/v8/src/ia32/lithium-codegen-ia32.cc +126 -80
  74. data/vendor/v8/src/ia32/lithium-codegen-ia32.h +2 -1
  75. data/vendor/v8/src/ia32/lithium-ia32.cc +15 -9
  76. data/vendor/v8/src/ia32/lithium-ia32.h +14 -6
  77. data/vendor/v8/src/ia32/macro-assembler-ia32.cc +50 -40
  78. data/vendor/v8/src/ia32/macro-assembler-ia32.h +5 -4
  79. data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.cc +113 -43
  80. data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.h +9 -4
  81. data/vendor/v8/src/ia32/simulator-ia32.h +4 -4
  82. data/vendor/v8/src/ia32/stub-cache-ia32.cc +52 -14
  83. data/vendor/v8/src/ic.cc +77 -20
  84. data/vendor/v8/src/ic.h +18 -2
  85. data/vendor/v8/src/incremental-marking-inl.h +21 -5
  86. data/vendor/v8/src/incremental-marking.cc +35 -8
  87. data/vendor/v8/src/incremental-marking.h +12 -3
  88. data/vendor/v8/src/isolate.cc +12 -2
  89. data/vendor/v8/src/isolate.h +1 -1
  90. data/vendor/v8/src/jsregexp.cc +66 -26
  91. data/vendor/v8/src/jsregexp.h +60 -31
  92. data/vendor/v8/src/list-inl.h +8 -0
  93. data/vendor/v8/src/list.h +3 -0
  94. data/vendor/v8/src/lithium.cc +5 -2
  95. data/vendor/v8/src/liveedit.cc +57 -5
  96. data/vendor/v8/src/mark-compact-inl.h +17 -11
  97. data/vendor/v8/src/mark-compact.cc +100 -143
  98. data/vendor/v8/src/mark-compact.h +44 -20
  99. data/vendor/v8/src/messages.js +131 -99
  100. data/vendor/v8/src/mips/builtins-mips.cc +5 -4
  101. data/vendor/v8/src/mips/code-stubs-mips.cc +23 -15
  102. data/vendor/v8/src/mips/codegen-mips.cc +2 -2
  103. data/vendor/v8/src/mips/debug-mips.cc +3 -1
  104. data/vendor/v8/src/mips/full-codegen-mips.cc +4 -102
  105. data/vendor/v8/src/mips/ic-mips.cc +34 -36
  106. data/vendor/v8/src/mips/lithium-codegen-mips.cc +116 -68
  107. data/vendor/v8/src/mips/lithium-mips.cc +20 -7
  108. data/vendor/v8/src/mips/lithium-mips.h +11 -4
  109. data/vendor/v8/src/mips/macro-assembler-mips.cc +50 -39
  110. data/vendor/v8/src/mips/macro-assembler-mips.h +5 -4
  111. data/vendor/v8/src/mips/regexp-macro-assembler-mips.cc +110 -50
  112. data/vendor/v8/src/mips/regexp-macro-assembler-mips.h +6 -5
  113. data/vendor/v8/src/mips/simulator-mips.h +5 -5
  114. data/vendor/v8/src/mips/stub-cache-mips.cc +66 -20
  115. data/vendor/v8/src/mksnapshot.cc +5 -1
  116. data/vendor/v8/src/objects-debug.cc +103 -6
  117. data/vendor/v8/src/objects-inl.h +215 -116
  118. data/vendor/v8/src/objects-printer.cc +13 -8
  119. data/vendor/v8/src/objects.cc +608 -331
  120. data/vendor/v8/src/objects.h +129 -94
  121. data/vendor/v8/src/parser.cc +16 -4
  122. data/vendor/v8/src/platform-freebsd.cc +1 -0
  123. data/vendor/v8/src/platform-linux.cc +9 -30
  124. data/vendor/v8/src/platform-posix.cc +28 -7
  125. data/vendor/v8/src/platform-win32.cc +15 -3
  126. data/vendor/v8/src/platform.h +2 -1
  127. data/vendor/v8/src/profile-generator-inl.h +25 -2
  128. data/vendor/v8/src/profile-generator.cc +300 -822
  129. data/vendor/v8/src/profile-generator.h +97 -214
  130. data/vendor/v8/src/regexp-macro-assembler-irregexp.cc +2 -1
  131. data/vendor/v8/src/regexp-macro-assembler-irregexp.h +2 -2
  132. data/vendor/v8/src/regexp-macro-assembler-tracer.cc +6 -5
  133. data/vendor/v8/src/regexp-macro-assembler-tracer.h +1 -1
  134. data/vendor/v8/src/regexp-macro-assembler.cc +7 -3
  135. data/vendor/v8/src/regexp-macro-assembler.h +10 -2
  136. data/vendor/v8/src/regexp.js +6 -0
  137. data/vendor/v8/src/runtime.cc +265 -212
  138. data/vendor/v8/src/runtime.h +6 -5
  139. data/vendor/v8/src/scopes.cc +20 -0
  140. data/vendor/v8/src/scopes.h +6 -3
  141. data/vendor/v8/src/spaces.cc +0 -2
  142. data/vendor/v8/src/string-stream.cc +2 -2
  143. data/vendor/v8/src/v8-counters.h +0 -2
  144. data/vendor/v8/src/v8natives.js +2 -2
  145. data/vendor/v8/src/v8utils.h +6 -3
  146. data/vendor/v8/src/version.cc +1 -1
  147. data/vendor/v8/src/x64/assembler-x64.h +2 -1
  148. data/vendor/v8/src/x64/builtins-x64.cc +5 -4
  149. data/vendor/v8/src/x64/code-stubs-x64.cc +25 -16
  150. data/vendor/v8/src/x64/codegen-x64.cc +2 -2
  151. data/vendor/v8/src/x64/debug-x64.cc +14 -1
  152. data/vendor/v8/src/x64/disasm-x64.cc +1 -1
  153. data/vendor/v8/src/x64/full-codegen-x64.cc +10 -106
  154. data/vendor/v8/src/x64/ic-x64.cc +20 -16
  155. data/vendor/v8/src/x64/lithium-codegen-x64.cc +156 -79
  156. data/vendor/v8/src/x64/lithium-codegen-x64.h +2 -1
  157. data/vendor/v8/src/x64/lithium-x64.cc +18 -8
  158. data/vendor/v8/src/x64/lithium-x64.h +7 -2
  159. data/vendor/v8/src/x64/macro-assembler-x64.cc +50 -40
  160. data/vendor/v8/src/x64/macro-assembler-x64.h +5 -4
  161. data/vendor/v8/src/x64/regexp-macro-assembler-x64.cc +122 -51
  162. data/vendor/v8/src/x64/regexp-macro-assembler-x64.h +17 -8
  163. data/vendor/v8/src/x64/simulator-x64.h +4 -4
  164. data/vendor/v8/src/x64/stub-cache-x64.cc +55 -17
  165. data/vendor/v8/test/cctest/cctest.status +1 -0
  166. data/vendor/v8/test/cctest/test-api.cc +24 -0
  167. data/vendor/v8/test/cctest/test-func-name-inference.cc +38 -0
  168. data/vendor/v8/test/cctest/test-heap-profiler.cc +21 -77
  169. data/vendor/v8/test/cctest/test-heap.cc +164 -3
  170. data/vendor/v8/test/cctest/test-list.cc +12 -0
  171. data/vendor/v8/test/cctest/test-mark-compact.cc +5 -5
  172. data/vendor/v8/test/cctest/test-regexp.cc +14 -8
  173. data/vendor/v8/test/cctest/testcfg.py +2 -0
  174. data/vendor/v8/test/mjsunit/accessor-map-sharing.js +176 -0
  175. data/vendor/v8/test/mjsunit/array-construct-transition.js +3 -3
  176. data/vendor/v8/test/mjsunit/array-literal-transitions.js +10 -10
  177. data/vendor/v8/test/mjsunit/big-array-literal.js +3 -0
  178. data/vendor/v8/test/mjsunit/compiler/inline-construct.js +4 -2
  179. data/vendor/v8/test/mjsunit/debug-liveedit-stack-padding.js +88 -0
  180. data/vendor/v8/test/mjsunit/elements-kind.js +4 -4
  181. data/vendor/v8/test/mjsunit/elements-transition-hoisting.js +2 -2
  182. data/vendor/v8/test/mjsunit/elements-transition.js +5 -5
  183. data/vendor/v8/test/mjsunit/error-constructors.js +68 -33
  184. data/vendor/v8/test/mjsunit/harmony/proxies.js +14 -6
  185. data/vendor/v8/test/mjsunit/mjsunit.status +1 -0
  186. data/vendor/v8/test/mjsunit/packed-elements.js +112 -0
  187. data/vendor/v8/test/mjsunit/regexp-capture-3.js +6 -0
  188. data/vendor/v8/test/mjsunit/regexp-global.js +132 -0
  189. data/vendor/v8/test/mjsunit/regexp.js +11 -0
  190. data/vendor/v8/test/mjsunit/regress/regress-117409.js +52 -0
  191. data/vendor/v8/test/mjsunit/regress/regress-126412.js +33 -0
  192. data/vendor/v8/test/mjsunit/regress/regress-128018.js +35 -0
  193. data/vendor/v8/test/mjsunit/regress/regress-128146.js +33 -0
  194. data/vendor/v8/test/mjsunit/regress/regress-1639-2.js +4 -1
  195. data/vendor/v8/test/mjsunit/regress/regress-1639.js +14 -8
  196. data/vendor/v8/test/mjsunit/regress/regress-1849.js +3 -3
  197. data/vendor/v8/test/mjsunit/regress/regress-1878.js +2 -2
  198. data/vendor/v8/test/mjsunit/regress/regress-2071.js +79 -0
  199. data/vendor/v8/test/mjsunit/regress/regress-2153.js +32 -0
  200. data/vendor/v8/test/mjsunit/regress/regress-crbug-122271.js +4 -4
  201. data/vendor/v8/test/mjsunit/regress/regress-crbug-126414.js +32 -0
  202. data/vendor/v8/test/mjsunit/regress/regress-smi-only-concat.js +2 -2
  203. data/vendor/v8/test/mjsunit/regress/regress-transcendental.js +49 -0
  204. data/vendor/v8/test/mjsunit/stack-traces.js +14 -0
  205. data/vendor/v8/test/mjsunit/unbox-double-arrays.js +4 -3
  206. data/vendor/v8/test/test262/testcfg.py +6 -1
  207. data/vendor/v8/tools/check-static-initializers.sh +11 -3
  208. data/vendor/v8/tools/fuzz-harness.sh +92 -0
  209. data/vendor/v8/tools/grokdump.py +658 -67
  210. data/vendor/v8/tools/gyp/v8.gyp +21 -39
  211. data/vendor/v8/tools/js2c.py +3 -3
  212. data/vendor/v8/tools/jsmin.py +2 -2
  213. data/vendor/v8/tools/presubmit.py +2 -1
  214. data/vendor/v8/tools/test-wrapper-gypbuild.py +25 -11
  215. metadata +624 -612
@@ -1,4 +1,4 @@
1
- // Copyright 2006-2008 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:
@@ -113,7 +113,7 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
113
113
  virtual void ReadStackPointerFromRegister(int reg);
114
114
  virtual void SetCurrentPositionFromEnd(int by);
115
115
  virtual void SetRegister(int register_index, int to);
116
- virtual void Succeed();
116
+ virtual bool Succeed();
117
117
  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
118
118
  virtual void ClearRegisters(int reg_from, int reg_to);
119
119
  virtual void WriteStackPointerToRegister(int reg);
@@ -137,7 +137,8 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
137
137
  static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
138
138
  // Stack parameters placed by caller.
139
139
  static const int kRegisterOutput = kSecondaryReturnAddress + kPointerSize;
140
- static const int kStackHighEnd = kRegisterOutput + kPointerSize;
140
+ static const int kNumOutputRegisters = kRegisterOutput + kPointerSize;
141
+ static const int kStackHighEnd = kNumOutputRegisters + kPointerSize;
141
142
  static const int kDirectCall = kStackHighEnd + kPointerSize;
142
143
  static const int kIsolate = kDirectCall + kPointerSize;
143
144
 
@@ -149,10 +150,10 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
149
150
  static const int kInputString = kStartIndex - kPointerSize;
150
151
  // When adding local variables remember to push space for them in
151
152
  // the frame in GetCode.
152
- static const int kInputStartMinusOne = kInputString - kPointerSize;
153
- static const int kAtStart = kInputStartMinusOne - kPointerSize;
153
+ static const int kSuccessfulCaptures = kInputString - kPointerSize;
154
+ static const int kInputStartMinusOne = kSuccessfulCaptures - kPointerSize;
154
155
  // First register address. Following registers are below it on the stack.
155
- static const int kRegisterZero = kAtStart - kPointerSize;
156
+ static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
156
157
 
157
158
  // Initial size of code buffer.
158
159
  static const size_t kRegExpCodeSize = 1024;
@@ -1,4 +1,4 @@
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:
@@ -49,16 +49,16 @@ namespace internal {
49
49
  (entry(p0, p1, p2, p3, p4))
50
50
 
51
51
  typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*,
52
- void*, int*, Address, int, Isolate*);
52
+ void*, int*, int, Address, int, Isolate*);
53
53
 
54
54
 
55
55
  // Call the generated regexp code directly. The code at the entry address
56
56
  // should act as a function matching the type arm_regexp_matcher.
57
57
  // The fifth argument is a dummy that reserves the space used for
58
58
  // the return address added by the ExitFrame in native calls.
59
- #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
59
+ #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
60
60
  (FUNCTION_CAST<arm_regexp_matcher>(entry)( \
61
- p0, p1, p2, p3, NULL, p4, p5, p6, p7))
61
+ p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8))
62
62
 
63
63
  #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
64
64
  reinterpret_cast<TryCatch*>(try_catch_address)
@@ -401,9 +401,9 @@ class Simulator {
401
401
  reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
402
402
  FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
403
403
 
404
- #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
404
+ #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
405
405
  Simulator::current(Isolate::Current())->Call( \
406
- entry, 9, p0, p1, p2, p3, NULL, p4, p5, p6, p7)
406
+ entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
407
407
 
408
408
  #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
409
409
  try_catch_address == NULL ? \
@@ -473,10 +473,20 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
473
473
  }
474
474
 
475
475
  if (!transition.is_null()) {
476
- // Update the map of the object; no write barrier updating is
477
- // needed because the map is never in new space.
478
- __ mov(ip, Operand(transition));
479
- __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
476
+ // Update the map of the object.
477
+ __ mov(scratch, Operand(transition));
478
+ __ str(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
479
+
480
+ // Update the write barrier for the map field and pass the now unused
481
+ // name_reg as scratch register.
482
+ __ RecordWriteField(receiver_reg,
483
+ HeapObject::kMapOffset,
484
+ scratch,
485
+ name_reg,
486
+ kLRHasNotBeenSaved,
487
+ kDontSaveFPRegs,
488
+ OMIT_REMEMBERED_SET,
489
+ OMIT_SMI_CHECK);
480
490
  }
481
491
 
482
492
  // Adjust for the number of properties stored in the object. Even in the
@@ -1273,12 +1283,19 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
1273
1283
  name, miss);
1274
1284
  ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
1275
1285
 
1286
+ // Preserve the receiver register explicitly whenever it is different from
1287
+ // the holder and it is needed should the interceptor return without any
1288
+ // result. The CALLBACKS case needs the receiver to be passed into C++ code,
1289
+ // the FIELD case might cause a miss during the prototype check.
1290
+ bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
1291
+ bool must_preserve_receiver_reg = !receiver.is(holder_reg) &&
1292
+ (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
1293
+
1276
1294
  // Save necessary data before invoking an interceptor.
1277
1295
  // Requires a frame to make GC aware of pushed pointers.
1278
1296
  {
1279
1297
  FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1280
- if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
1281
- // CALLBACKS case needs a receiver to be passed into C++ callback.
1298
+ if (must_preserve_receiver_reg) {
1282
1299
  __ Push(receiver, holder_reg, name_reg);
1283
1300
  } else {
1284
1301
  __ Push(holder_reg, name_reg);
@@ -1303,14 +1320,14 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
1303
1320
  __ bind(&interceptor_failed);
1304
1321
  __ pop(name_reg);
1305
1322
  __ pop(holder_reg);
1306
- if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
1323
+ if (must_preserve_receiver_reg) {
1307
1324
  __ pop(receiver);
1308
1325
  }
1309
1326
  // Leave the internal frame.
1310
1327
  }
1311
1328
  // Check that the maps from interceptor's holder to lookup's holder
1312
1329
  // haven't changed. And load lookup's holder into |holder| register.
1313
- if (*interceptor_holder != lookup->holder()) {
1330
+ if (must_perfrom_prototype_check) {
1314
1331
  holder_reg = CheckPrototypes(interceptor_holder,
1315
1332
  holder_reg,
1316
1333
  Handle<JSObject>(lookup->holder()),
@@ -1574,16 +1591,29 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
1574
1591
  __ jmp(&fast_object);
1575
1592
  // In case of fast smi-only, convert to fast object, otherwise bail out.
1576
1593
  __ bind(&not_fast_object);
1577
- __ CheckFastSmiOnlyElements(r3, r7, &call_builtin);
1594
+ __ CheckFastSmiElements(r3, r7, &call_builtin);
1578
1595
  // edx: receiver
1579
1596
  // r3: map
1580
- __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
1597
+ Label try_holey_map;
1598
+ __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
1581
1599
  FAST_ELEMENTS,
1582
1600
  r3,
1583
1601
  r7,
1602
+ &try_holey_map);
1603
+ __ mov(r2, receiver);
1604
+ ElementsTransitionGenerator::
1605
+ GenerateMapChangeElementsTransition(masm());
1606
+ __ jmp(&fast_object);
1607
+
1608
+ __ bind(&try_holey_map);
1609
+ __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
1610
+ FAST_HOLEY_ELEMENTS,
1611
+ r3,
1612
+ r7,
1584
1613
  &call_builtin);
1585
1614
  __ mov(r2, receiver);
1586
- ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm());
1615
+ ElementsTransitionGenerator::
1616
+ GenerateMapChangeElementsTransition(masm());
1587
1617
  __ bind(&fast_object);
1588
1618
  } else {
1589
1619
  __ CheckFastObjectElements(r3, r3, &call_builtin);
@@ -3365,8 +3395,11 @@ static bool IsElementTypeSigned(ElementsKind elements_kind) {
3365
3395
  case EXTERNAL_FLOAT_ELEMENTS:
3366
3396
  case EXTERNAL_DOUBLE_ELEMENTS:
3367
3397
  case FAST_ELEMENTS:
3368
- case FAST_SMI_ONLY_ELEMENTS:
3398
+ case FAST_SMI_ELEMENTS:
3369
3399
  case FAST_DOUBLE_ELEMENTS:
3400
+ case FAST_HOLEY_ELEMENTS:
3401
+ case FAST_HOLEY_SMI_ELEMENTS:
3402
+ case FAST_HOLEY_DOUBLE_ELEMENTS:
3370
3403
  case DICTIONARY_ELEMENTS:
3371
3404
  case NON_STRICT_ARGUMENTS_ELEMENTS:
3372
3405
  UNREACHABLE();
@@ -3490,8 +3523,11 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3490
3523
  }
3491
3524
  break;
3492
3525
  case FAST_ELEMENTS:
3493
- case FAST_SMI_ONLY_ELEMENTS:
3526
+ case FAST_SMI_ELEMENTS:
3494
3527
  case FAST_DOUBLE_ELEMENTS:
3528
+ case FAST_HOLEY_ELEMENTS:
3529
+ case FAST_HOLEY_SMI_ELEMENTS:
3530
+ case FAST_HOLEY_DOUBLE_ELEMENTS:
3495
3531
  case DICTIONARY_ELEMENTS:
3496
3532
  case NON_STRICT_ARGUMENTS_ELEMENTS:
3497
3533
  UNREACHABLE();
@@ -3831,8 +3867,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3831
3867
  }
3832
3868
  break;
3833
3869
  case FAST_ELEMENTS:
3834
- case FAST_SMI_ONLY_ELEMENTS:
3870
+ case FAST_SMI_ELEMENTS:
3835
3871
  case FAST_DOUBLE_ELEMENTS:
3872
+ case FAST_HOLEY_ELEMENTS:
3873
+ case FAST_HOLEY_SMI_ELEMENTS:
3874
+ case FAST_HOLEY_DOUBLE_ELEMENTS:
3836
3875
  case DICTIONARY_ELEMENTS:
3837
3876
  case NON_STRICT_ARGUMENTS_ELEMENTS:
3838
3877
  UNREACHABLE();
@@ -3895,8 +3934,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3895
3934
  case EXTERNAL_FLOAT_ELEMENTS:
3896
3935
  case EXTERNAL_DOUBLE_ELEMENTS:
3897
3936
  case FAST_ELEMENTS:
3898
- case FAST_SMI_ONLY_ELEMENTS:
3937
+ case FAST_SMI_ELEMENTS:
3899
3938
  case FAST_DOUBLE_ELEMENTS:
3939
+ case FAST_HOLEY_ELEMENTS:
3940
+ case FAST_HOLEY_SMI_ELEMENTS:
3941
+ case FAST_HOLEY_DOUBLE_ELEMENTS:
3900
3942
  case DICTIONARY_ELEMENTS:
3901
3943
  case NON_STRICT_ARGUMENTS_ELEMENTS:
3902
3944
  UNREACHABLE();
@@ -4035,8 +4077,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
4035
4077
  case EXTERNAL_FLOAT_ELEMENTS:
4036
4078
  case EXTERNAL_DOUBLE_ELEMENTS:
4037
4079
  case FAST_ELEMENTS:
4038
- case FAST_SMI_ONLY_ELEMENTS:
4080
+ case FAST_SMI_ELEMENTS:
4039
4081
  case FAST_DOUBLE_ELEMENTS:
4082
+ case FAST_HOLEY_ELEMENTS:
4083
+ case FAST_HOLEY_SMI_ELEMENTS:
4084
+ case FAST_HOLEY_DOUBLE_ELEMENTS:
4040
4085
  case DICTIONARY_ELEMENTS:
4041
4086
  case NON_STRICT_ARGUMENTS_ELEMENTS:
4042
4087
  UNREACHABLE();
@@ -4218,7 +4263,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
4218
4263
  // Check that the key is a smi or a heap number convertible to a smi.
4219
4264
  GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, &miss_force_generic);
4220
4265
 
4221
- if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
4266
+ if (IsFastSmiElementsKind(elements_kind)) {
4222
4267
  __ JumpIfNotSmi(value_reg, &transition_elements_kind);
4223
4268
  }
4224
4269
 
@@ -4246,7 +4291,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
4246
4291
  DONT_DO_SMI_CHECK);
4247
4292
 
4248
4293
  __ bind(&finish_store);
4249
- if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
4294
+ if (IsFastSmiElementsKind(elements_kind)) {
4250
4295
  __ add(scratch,
4251
4296
  elements_reg,
4252
4297
  Operand(FixedArray::kHeaderSize - kHeapObjectTag));
@@ -4256,7 +4301,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
4256
4301
  Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
4257
4302
  __ str(value_reg, MemOperand(scratch));
4258
4303
  } else {
4259
- ASSERT(elements_kind == FAST_ELEMENTS);
4304
+ ASSERT(IsFastObjectElementsKind(elements_kind));
4260
4305
  __ add(scratch,
4261
4306
  elements_reg,
4262
4307
  Operand(FixedArray::kHeaderSize - kHeapObjectTag));
@@ -827,7 +827,8 @@ function ArraySort(comparefn) {
827
827
  var element = a[i];
828
828
  var order = %_CallFunction(receiver, element, pivot, comparefn);
829
829
  if (order < 0) {
830
- %_SwapElements(a, i, low_end);
830
+ a[i] = a[low_end];
831
+ a[low_end] = element;
831
832
  low_end++;
832
833
  } else if (order > 0) {
833
834
  do {
@@ -836,9 +837,12 @@ function ArraySort(comparefn) {
836
837
  var top_elem = a[high_start];
837
838
  order = %_CallFunction(receiver, top_elem, pivot, comparefn);
838
839
  } while (order > 0);
839
- %_SwapElements(a, i, high_start);
840
+ a[i] = a[high_start];
841
+ a[high_start] = element;
840
842
  if (order < 0) {
841
- %_SwapElements(a, i, low_end);
843
+ element = a[i];
844
+ a[i] = a[low_end];
845
+ a[low_end] = element;
842
846
  low_end++;
843
847
  }
844
848
  }
@@ -962,6 +962,14 @@ RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
962
962
  }
963
963
 
964
964
 
965
+ static int IncreaseBy(int previous, int increase) {
966
+ if (RegExpTree::kInfinity - previous < increase) {
967
+ return RegExpTree::kInfinity;
968
+ } else {
969
+ return previous + increase;
970
+ }
971
+ }
972
+
965
973
  RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
966
974
  : nodes_(nodes) {
967
975
  ASSERT(nodes->length() > 1);
@@ -969,13 +977,10 @@ RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
969
977
  max_match_ = 0;
970
978
  for (int i = 0; i < nodes->length(); i++) {
971
979
  RegExpTree* node = nodes->at(i);
972
- min_match_ += node->min_match();
980
+ int node_min_match = node->min_match();
981
+ min_match_ = IncreaseBy(min_match_, node_min_match);
973
982
  int node_max_match = node->max_match();
974
- if (kInfinity - max_match_ < node_max_match) {
975
- max_match_ = kInfinity;
976
- } else {
977
- max_match_ += node->max_match();
978
- }
983
+ max_match_ = IncreaseBy(max_match_, node_max_match);
979
984
  }
980
985
  }
981
986
 
@@ -484,8 +484,8 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
484
484
 
485
485
  global_context()->set_initial_object_prototype(*prototype);
486
486
  SetPrototype(object_fun, prototype);
487
- object_function_map->
488
- set_instance_descriptors(heap->empty_descriptor_array());
487
+ object_function_map->set_instance_descriptors(
488
+ heap->empty_descriptor_array());
489
489
  }
490
490
 
491
491
  // Allocate the empty function as the prototype for function ECMAScript
@@ -516,12 +516,10 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
516
516
  function_instance_map_writable_prototype_->set_prototype(*empty_function);
517
517
 
518
518
  // Allocate the function map first and then patch the prototype later
519
- Handle<Map> empty_fm = factory->CopyMapDropDescriptors(
520
- function_without_prototype_map);
521
- empty_fm->set_instance_descriptors(
522
- function_without_prototype_map->instance_descriptors());
523
- empty_fm->set_prototype(global_context()->object_function()->prototype());
524
- empty_function->set_map(*empty_fm);
519
+ Handle<Map> empty_function_map = CreateFunctionMap(DONT_ADD_PROTOTYPE);
520
+ empty_function_map->set_prototype(
521
+ global_context()->object_function()->prototype());
522
+ empty_function->set_map(*empty_function_map);
525
523
  return empty_function;
526
524
  }
527
525
 
@@ -1094,7 +1092,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
1094
1092
 
1095
1093
  // Check the state of the object.
1096
1094
  ASSERT(result->HasFastProperties());
1097
- ASSERT(result->HasFastElements());
1095
+ ASSERT(result->HasFastObjectElements());
1098
1096
  #endif
1099
1097
  }
1100
1098
 
@@ -1187,7 +1185,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
1187
1185
 
1188
1186
  // Check the state of the object.
1189
1187
  ASSERT(result->HasFastProperties());
1190
- ASSERT(result->HasFastElements());
1188
+ ASSERT(result->HasFastObjectElements());
1191
1189
  #endif
1192
1190
  }
1193
1191
 
@@ -1637,7 +1635,7 @@ bool Genesis::InstallNatives() {
1637
1635
  array_function->initial_map()->CopyDropTransitions();
1638
1636
  Map* new_map;
1639
1637
  if (!maybe_map->To<Map>(&new_map)) return false;
1640
- new_map->set_elements_kind(FAST_ELEMENTS);
1638
+ new_map->set_elements_kind(FAST_HOLEY_ELEMENTS);
1641
1639
  array_function->set_initial_map(new_map);
1642
1640
 
1643
1641
  // Make "length" magic on instances.
@@ -200,9 +200,12 @@ static MaybeObject* ArrayCodeGenericCommon(Arguments* args,
200
200
  array->set_elements(heap->empty_fixed_array());
201
201
  if (!FLAG_smi_only_arrays) {
202
202
  Context* global_context = isolate->context()->global_context();
203
- if (array->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS &&
204
- !global_context->object_js_array_map()->IsUndefined()) {
205
- array->set_map(Map::cast(global_context->object_js_array_map()));
203
+ if (array->GetElementsKind() == GetInitialFastElementsKind() &&
204
+ !global_context->js_array_maps()->IsUndefined()) {
205
+ FixedArray* map_array =
206
+ FixedArray::cast(global_context->js_array_maps());
207
+ array->set_map(Map::cast(map_array->
208
+ get(TERMINAL_FAST_ELEMENTS_KIND)));
206
209
  }
207
210
  }
208
211
  } else {
@@ -222,6 +225,13 @@ static MaybeObject* ArrayCodeGenericCommon(Arguments* args,
222
225
  { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len);
223
226
  if (!maybe_obj->ToObject(&fixed_array)) return maybe_obj;
224
227
  }
228
+ ElementsKind elements_kind = array->GetElementsKind();
229
+ if (!IsFastHoleyElementsKind(elements_kind)) {
230
+ elements_kind = GetHoleyElementsKind(elements_kind);
231
+ MaybeObject* maybe_array =
232
+ array->TransitionElementsKind(elements_kind);
233
+ if (maybe_array->IsFailure()) return maybe_array;
234
+ }
225
235
  // We do not use SetContent to skip the unnecessary elements type check.
226
236
  array->set_elements(FixedArray::cast(fixed_array));
227
237
  array->set_length(Smi::cast(obj));
@@ -250,7 +260,7 @@ static MaybeObject* ArrayCodeGenericCommon(Arguments* args,
250
260
  // Allocate an appropriately typed elements array.
251
261
  MaybeObject* maybe_elms;
252
262
  ElementsKind elements_kind = array->GetElementsKind();
253
- if (elements_kind == FAST_DOUBLE_ELEMENTS) {
263
+ if (IsFastDoubleElementsKind(elements_kind)) {
254
264
  maybe_elms = heap->AllocateUninitializedFixedDoubleArray(
255
265
  number_of_elements);
256
266
  } else {
@@ -261,13 +271,15 @@ static MaybeObject* ArrayCodeGenericCommon(Arguments* args,
261
271
 
262
272
  // Fill in the content
263
273
  switch (array->GetElementsKind()) {
264
- case FAST_SMI_ONLY_ELEMENTS: {
274
+ case FAST_HOLEY_SMI_ELEMENTS:
275
+ case FAST_SMI_ELEMENTS: {
265
276
  FixedArray* smi_elms = FixedArray::cast(elms);
266
277
  for (int index = 0; index < number_of_elements; index++) {
267
278
  smi_elms->set(index, (*args)[index+1], SKIP_WRITE_BARRIER);
268
279
  }
269
280
  break;
270
281
  }
282
+ case FAST_HOLEY_ELEMENTS:
271
283
  case FAST_ELEMENTS: {
272
284
  AssertNoAllocation no_gc;
273
285
  WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
@@ -277,6 +289,7 @@ static MaybeObject* ArrayCodeGenericCommon(Arguments* args,
277
289
  }
278
290
  break;
279
291
  }
292
+ case FAST_HOLEY_DOUBLE_ELEMENTS:
280
293
  case FAST_DOUBLE_ELEMENTS: {
281
294
  FixedDoubleArray* double_elms = FixedDoubleArray::cast(elms);
282
295
  for (int index = 0; index < number_of_elements; index++) {
@@ -412,12 +425,17 @@ static inline MaybeObject* EnsureJSArrayWithWritableFastElements(
412
425
  HeapObject* elms = array->elements();
413
426
  Map* map = elms->map();
414
427
  if (map == heap->fixed_array_map()) {
415
- if (args == NULL || !array->HasFastSmiOnlyElements()) {
428
+ if (args == NULL || array->HasFastObjectElements()) return elms;
429
+ if (array->HasFastDoubleElements()) {
430
+ ASSERT(elms == heap->empty_fixed_array());
431
+ MaybeObject* maybe_transition =
432
+ array->TransitionElementsKind(FAST_ELEMENTS);
433
+ if (maybe_transition->IsFailure()) return maybe_transition;
416
434
  return elms;
417
435
  }
418
436
  } else if (map == heap->fixed_cow_array_map()) {
419
437
  MaybeObject* maybe_writable_result = array->EnsureWritableFastElements();
420
- if (args == NULL || !array->HasFastSmiOnlyElements() ||
438
+ if (args == NULL || array->HasFastObjectElements() ||
421
439
  maybe_writable_result->IsFailure()) {
422
440
  return maybe_writable_result;
423
441
  }
@@ -511,8 +529,8 @@ BUILTIN(ArrayPush) {
511
529
  }
512
530
  FixedArray* new_elms = FixedArray::cast(obj);
513
531
 
514
- CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0,
515
- new_elms, FAST_ELEMENTS, 0, len);
532
+ ElementsKind kind = array->GetElementsKind();
533
+ CopyObjectToObjectElements(elms, kind, 0, new_elms, kind, 0, len);
516
534
  FillWithHoles(heap, new_elms, new_length, capacity);
517
535
 
518
536
  elms = new_elms;
@@ -583,7 +601,7 @@ BUILTIN(ArrayShift) {
583
601
  }
584
602
  FixedArray* elms = FixedArray::cast(elms_obj);
585
603
  JSArray* array = JSArray::cast(receiver);
586
- ASSERT(array->HasFastTypeElements());
604
+ ASSERT(array->HasFastSmiOrObjectElements());
587
605
 
588
606
  int len = Smi::cast(array->length())->value();
589
607
  if (len == 0) return heap->undefined_value();
@@ -625,7 +643,7 @@ BUILTIN(ArrayUnshift) {
625
643
  }
626
644
  FixedArray* elms = FixedArray::cast(elms_obj);
627
645
  JSArray* array = JSArray::cast(receiver);
628
- ASSERT(array->HasFastTypeElements());
646
+ ASSERT(array->HasFastSmiOrObjectElements());
629
647
 
630
648
  int len = Smi::cast(array->length())->value();
631
649
  int to_add = args.length() - 1;
@@ -647,8 +665,8 @@ BUILTIN(ArrayUnshift) {
647
665
  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
648
666
  }
649
667
  FixedArray* new_elms = FixedArray::cast(obj);
650
- CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0,
651
- new_elms, FAST_ELEMENTS, to_add, len);
668
+ ElementsKind kind = array->GetElementsKind();
669
+ CopyObjectToObjectElements(elms, kind, 0, new_elms, kind, to_add, len);
652
670
  FillWithHoles(heap, new_elms, new_length, capacity);
653
671
  elms = new_elms;
654
672
  array->set_elements(elms);
@@ -677,7 +695,7 @@ BUILTIN(ArraySlice) {
677
695
  int len = -1;
678
696
  if (receiver->IsJSArray()) {
679
697
  JSArray* array = JSArray::cast(receiver);
680
- if (!array->HasFastTypeElements() ||
698
+ if (!array->HasFastSmiOrObjectElements() ||
681
699
  !IsJSArrayFastElementMovingAllowed(heap, array)) {
682
700
  return CallJsBuiltin(isolate, "ArraySlice", args);
683
701
  }
@@ -693,7 +711,7 @@ BUILTIN(ArraySlice) {
693
711
  bool is_arguments_object_with_fast_elements =
694
712
  receiver->IsJSObject()
695
713
  && JSObject::cast(receiver)->map() == arguments_map
696
- && JSObject::cast(receiver)->HasFastTypeElements();
714
+ && JSObject::cast(receiver)->HasFastSmiOrObjectElements();
697
715
  if (!is_arguments_object_with_fast_elements) {
698
716
  return CallJsBuiltin(isolate, "ArraySlice", args);
699
717
  }
@@ -758,9 +776,9 @@ BUILTIN(ArraySlice) {
758
776
  JSArray* result_array;
759
777
  if (!maybe_array->To(&result_array)) return maybe_array;
760
778
 
761
- CopyObjectToObjectElements(elms, FAST_ELEMENTS, k,
779
+ CopyObjectToObjectElements(elms, elements_kind, k,
762
780
  FixedArray::cast(result_array->elements()),
763
- FAST_ELEMENTS, 0, result_len);
781
+ elements_kind, 0, result_len);
764
782
 
765
783
  return result_array;
766
784
  }
@@ -781,7 +799,7 @@ BUILTIN(ArraySplice) {
781
799
  }
782
800
  FixedArray* elms = FixedArray::cast(elms_obj);
783
801
  JSArray* array = JSArray::cast(receiver);
784
- ASSERT(array->HasFastTypeElements());
802
+ ASSERT(array->HasFastSmiOrObjectElements());
785
803
 
786
804
  int len = Smi::cast(array->length())->value();
787
805
 
@@ -832,9 +850,9 @@ BUILTIN(ArraySplice) {
832
850
 
833
851
  {
834
852
  // Fill newly created array.
835
- CopyObjectToObjectElements(elms, FAST_ELEMENTS, actual_start,
853
+ CopyObjectToObjectElements(elms, elements_kind, actual_start,
836
854
  FixedArray::cast(result_array->elements()),
837
- FAST_ELEMENTS, 0, actual_delete_count);
855
+ elements_kind, 0, actual_delete_count);
838
856
  }
839
857
 
840
858
  int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
@@ -883,12 +901,13 @@ BUILTIN(ArraySplice) {
883
901
 
884
902
  {
885
903
  // Copy the part before actual_start as is.
886
- CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0,
887
- new_elms, FAST_ELEMENTS, 0, actual_start);
904
+ ElementsKind kind = array->GetElementsKind();
905
+ CopyObjectToObjectElements(elms, kind, 0,
906
+ new_elms, kind, 0, actual_start);
888
907
  const int to_copy = len - actual_delete_count - actual_start;
889
- CopyObjectToObjectElements(elms, FAST_ELEMENTS,
908
+ CopyObjectToObjectElements(elms, kind,
890
909
  actual_start + actual_delete_count,
891
- new_elms, FAST_ELEMENTS,
910
+ new_elms, kind,
892
911
  actual_start + item_count, to_copy);
893
912
  }
894
913
 
@@ -935,11 +954,12 @@ BUILTIN(ArrayConcat) {
935
954
  // and calculating total length.
936
955
  int n_arguments = args.length();
937
956
  int result_len = 0;
938
- ElementsKind elements_kind = FAST_SMI_ONLY_ELEMENTS;
957
+ ElementsKind elements_kind = GetInitialFastElementsKind();
939
958
  for (int i = 0; i < n_arguments; i++) {
940
959
  Object* arg = args[i];
941
- if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastTypeElements()
942
- || JSArray::cast(arg)->GetPrototype() != array_proto) {
960
+ if (!arg->IsJSArray() ||
961
+ !JSArray::cast(arg)->HasFastSmiOrObjectElements() ||
962
+ JSArray::cast(arg)->GetPrototype() != array_proto) {
943
963
  return CallJsBuiltin(isolate, "ArrayConcat", args);
944
964
  }
945
965
 
@@ -956,8 +976,18 @@ BUILTIN(ArrayConcat) {
956
976
  return CallJsBuiltin(isolate, "ArrayConcat", args);
957
977
  }
958
978
 
959
- if (!JSArray::cast(arg)->HasFastSmiOnlyElements()) {
960
- elements_kind = FAST_ELEMENTS;
979
+ if (!JSArray::cast(arg)->HasFastSmiElements()) {
980
+ if (IsFastSmiElementsKind(elements_kind)) {
981
+ if (IsFastHoleyElementsKind(elements_kind)) {
982
+ elements_kind = FAST_HOLEY_ELEMENTS;
983
+ } else {
984
+ elements_kind = FAST_ELEMENTS;
985
+ }
986
+ }
987
+ }
988
+
989
+ if (JSArray::cast(arg)->HasFastHoleyElements()) {
990
+ elements_kind = GetHoleyElementsKind(elements_kind);
961
991
  }
962
992
  }
963
993
 
@@ -977,8 +1007,8 @@ BUILTIN(ArrayConcat) {
977
1007
  JSArray* array = JSArray::cast(args[i]);
978
1008
  int len = Smi::cast(array->length())->value();
979
1009
  FixedArray* elms = FixedArray::cast(array->elements());
980
- CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0,
981
- result_elms, FAST_ELEMENTS,
1010
+ CopyObjectToObjectElements(elms, elements_kind, 0,
1011
+ result_elms, elements_kind,
982
1012
  start_pos, len);
983
1013
  start_pos += len;
984
1014
  }