Browse Source

deps: upgrade to V8 4.9.385.35

PR-URL: https://github.com/nodejs/node/pull/6077
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
process-exit-stdio-flushing
Ben Noordhuis 9 years ago
parent
commit
3a8e8230ee
  1. 2
      deps/v8/include/v8-version.h
  2. 6
      deps/v8/include/v8.h
  3. 13
      deps/v8/src/arm/deoptimizer-arm.cc
  4. 10
      deps/v8/src/arm64/deoptimizer-arm64.cc
  5. 108
      deps/v8/src/builtins.cc
  6. 10
      deps/v8/src/compiler/pipeline.cc
  7. 8
      deps/v8/src/compiler/simplified-lowering.cc
  8. 5
      deps/v8/src/compiler/simplified-lowering.h
  9. 37
      deps/v8/src/elements.cc
  10. 2
      deps/v8/src/elements.h
  11. 13
      deps/v8/src/heap/incremental-marking.cc
  12. 7
      deps/v8/src/heap/memory-reducer.cc
  13. 6
      deps/v8/src/runtime/runtime-array.cc
  14. 1
      deps/v8/test/cctest/cctest.gyp
  15. 142
      deps/v8/test/cctest/compiler/test-run-properties.cc
  16. 13
      deps/v8/test/mjsunit/array-concat.js
  17. 6
      deps/v8/test/mjsunit/array-sort.js
  18. 76
      deps/v8/test/mjsunit/regress/regress-4800.js
  19. 20
      deps/v8/test/mjsunit/regress/regress-crbug-589792.js
  20. 36
      deps/v8/test/mjsunit/regress/regress-crbug-594574-concat-leak-1.js
  21. 35
      deps/v8/test/mjsunit/regress/regress-crbug-594574-concat-leak-2.js

2
deps/v8/include/v8-version.h

@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 4
#define V8_MINOR_VERSION 9
#define V8_BUILD_NUMBER 385
#define V8_PATCH_LEVEL 27
#define V8_PATCH_LEVEL 35
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)

6
deps/v8/include/v8.h

@ -2678,9 +2678,9 @@ class V8_EXPORT Object : public Value {
V8_DEPRECATED("Use CreateDataProperty / DefineOwnProperty",
bool ForceSet(Local<Value> key, Local<Value> value,
PropertyAttribute attribs = None));
V8_DEPRECATED("Use CreateDataProperty / DefineOwnProperty",
Maybe<bool> ForceSet(Local<Context> context, Local<Value> key,
Local<Value> value,
V8_DEPRECATE_SOON("Use CreateDataProperty / DefineOwnProperty",
Maybe<bool> ForceSet(Local<Context> context,
Local<Value> key, Local<Value> value,
PropertyAttribute attribs = None));
V8_DEPRECATE_SOON("Use maybe version", Local<Value> Get(Local<Value> key));

13
deps/v8/src/arm/deoptimizer-arm.cc

@ -288,14 +288,11 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ CheckFor32DRegs(ip);
__ ldr(r1, MemOperand(r0, Deoptimizer::input_offset()));
int src_offset = FrameDescription::double_registers_offset();
for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; ++i) {
if (i == kDoubleRegZero.code()) continue;
if (i == kScratchDoubleReg.code()) continue;
const DwVfpRegister reg = DwVfpRegister::from_code(i);
__ vldr(reg, r1, src_offset, i < 16 ? al : ne);
src_offset += kDoubleSize;
for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
int code = config->GetAllocatableDoubleCode(i);
DwVfpRegister reg = DwVfpRegister::from_code(code);
int src_offset = code * kDoubleSize + double_regs_offset;
__ vldr(reg, r1, src_offset);
}
// Push state, pc, and continuation from the last output frame.

10
deps/v8/src/arm64/deoptimizer-arm64.cc

@ -191,11 +191,13 @@ void Deoptimizer::TableEntryGenerator::Generate() {
}
// Copy FP registers to the input frame.
CPURegList copy_fp_to_input = saved_fp_registers;
for (int i = 0; i < saved_fp_registers.Count(); i++) {
int dst_offset = FrameDescription::double_registers_offset() +
(i * kDoubleSize);
int src_offset = kFPRegistersOffset + (i * kDoubleSize);
__ Peek(x2, src_offset);
CPURegister reg = copy_fp_to_input.PopLowestIndex();
int dst_offset = FrameDescription::double_registers_offset() +
(reg.code() * kDoubleSize);
__ Str(x2, MemOperand(x1, dst_offset));
}
@ -264,11 +266,11 @@ void Deoptimizer::TableEntryGenerator::Generate() {
DCHECK(!saved_fp_registers.IncludesAliasOf(crankshaft_fp_scratch) &&
!saved_fp_registers.IncludesAliasOf(fp_zero) &&
!saved_fp_registers.IncludesAliasOf(fp_scratch));
int src_offset = FrameDescription::double_registers_offset();
while (!saved_fp_registers.IsEmpty()) {
const CPURegister reg = saved_fp_registers.PopLowestIndex();
int src_offset = FrameDescription::double_registers_offset() +
(reg.code() * kDoubleSize);
__ Ldr(reg, MemOperand(x1, src_offset));
src_offset += kDoubleSize;
}
// Push state from the last output frame.

108
deps/v8/src/builtins.cc

@ -208,6 +208,7 @@ inline bool PrototypeHasNoElements(PrototypeIterator* iter) {
JSObject* current = iter->GetCurrent<JSObject>();
if (current->IsAccessCheckNeeded()) return false;
if (current->HasIndexedInterceptor()) return false;
if (current->IsJSValue()) return false;
if (current->elements()->length() != 0) return false;
}
return true;
@ -232,6 +233,41 @@ inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
}
inline bool HasSimpleElements(JSObject* current) {
if (current->IsAccessCheckNeeded()) return false;
if (current->HasIndexedInterceptor()) return false;
if (current->IsJSValue()) return false;
if (current->GetElementsAccessor()->HasAccessors(current)) return false;
return true;
}
inline bool HasOnlySimpleReceiverElements(Isolate* isolate,
JSReceiver* receiver) {
// Check that we have no accessors on the receiver's elements.
JSObject* object = JSObject::cast(receiver);
if (!HasSimpleElements(object)) return false;
// Check that ther are not elements on the prototype.
DisallowHeapAllocation no_gc;
PrototypeIterator iter(isolate, receiver);
return PrototypeHasNoElements(&iter);
}
inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
// Check that ther are not elements on the prototype.
DisallowHeapAllocation no_gc;
PrototypeIterator iter(isolate, receiver,
PrototypeIterator::START_AT_RECEIVER);
for (; !iter.IsAtEnd(); iter.Advance()) {
if (iter.GetCurrent()->IsJSProxy()) return false;
JSObject* current = iter.GetCurrent<JSObject>();
if (!HasSimpleElements(current)) return false;
}
return true;
}
// Returns empty handle if not applicable.
MUST_USE_RESULT
inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
@ -1013,9 +1049,10 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
if (!val->ToUint32(&length)) {
length = 0;
}
return IterateElementsSlow(isolate, receiver, length, visitor);
}
if (!(receiver->IsJSArray() || receiver->IsJSTypedArray())) {
if (!HasOnlySimpleElements(isolate, *receiver)) {
// For classes which are not known to be safe to access via elements alone,
// use the slow case.
return IterateElementsSlow(isolate, receiver, length, visitor);
@ -1031,7 +1068,7 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
// to check the prototype for missing elements.
Handle<FixedArray> elements(FixedArray::cast(array->elements()));
int fast_length = static_cast<int>(length);
DCHECK(fast_length <= elements->length());
DCHECK_LE(fast_length, elements->length());
for (int j = 0; j < fast_length; j++) {
HandleScope loop_scope(isolate);
Handle<Object> element_value(elements->get(j), isolate);
@ -1090,14 +1127,6 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
break;
}
case DICTIONARY_ELEMENTS: {
// CollectElementIndices() can't be called when there's a JSProxy
// on the prototype chain.
for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd();
iter.Advance()) {
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
return IterateElementsSlow(isolate, array, length, visitor);
}
}
Handle<SeededNumberDictionary> dict(array->element_dictionary());
List<uint32_t> indices(dict->Capacity() / 2);
// Collect all indices in the object and the prototypes less
@ -1187,7 +1216,6 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
DCHECK(isolate->IsFastArrayConstructorPrototypeChainIntact());
if (!FLAG_harmony_concat_spreadable) return false;
Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
@ -1232,17 +1260,14 @@ Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
length_estimate = static_cast<uint32_t>(array->length()->Number());
if (length_estimate != 0) {
ElementsKind array_kind =
GetPackedElementsKind(array->map()->elements_kind());
GetPackedElementsKind(array->GetElementsKind());
kind = GetMoreGeneralElementsKind(kind, array_kind);
}
element_estimate = EstimateElementCount(array);
} else {
if (obj->IsHeapObject()) {
if (obj->IsNumber()) {
kind = GetMoreGeneralElementsKind(kind, FAST_DOUBLE_ELEMENTS);
} else {
kind = GetMoreGeneralElementsKind(kind, FAST_ELEMENTS);
}
kind = GetMoreGeneralElementsKind(
kind, obj->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS);
}
length_estimate = 1;
element_estimate = 1;
@ -1284,7 +1309,7 @@ Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
} else {
JSArray* array = JSArray::cast(*obj);
uint32_t length = static_cast<uint32_t>(array->length()->Number());
switch (array->map()->elements_kind()) {
switch (array->GetElementsKind()) {
case FAST_HOLEY_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS: {
// Empty array is FixedArray but not FixedDoubleArray.
@ -1335,14 +1360,7 @@ Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
}
}
if (!failure) {
Handle<JSArray> array = isolate->factory()->NewJSArray(0);
Smi* length = Smi::FromInt(j);
Handle<Map> map;
map = JSObject::GetElementsTransitionMap(array, kind);
array->set_map(*map);
array->set_length(length);
array->set_elements(*storage);
return *array;
return *isolate->factory()->NewJSArrayWithElements(storage, kind, j);
}
// In case of failure, fall through.
}
@ -1387,23 +1405,23 @@ Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) {
return MaybeHandle<JSArray>();
}
int n_arguments = args->length();
int result_len = 0;
{
DisallowHeapAllocation no_gc;
Object* array_proto = isolate->array_function()->prototype();
// Iterate through all the arguments performing checks
// and calculating total length.
for (int i = 0; i < n_arguments; i++) {
Object* arg = (*args)[i];
if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
return MaybeHandle<JSArray>();
}
// TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
if (!JSObject::cast(arg)->HasFastElements()) {
return MaybeHandle<JSArray>();
}
Handle<JSArray> array(JSArray::cast(arg), isolate);
if (!array->HasFastElements()) return MaybeHandle<JSArray>();
PrototypeIterator iter(isolate, arg);
if (iter.GetCurrent() != array_proto) return MaybeHandle<JSArray>();
if (HasConcatSpreadableModifier(isolate, array)) {
return MaybeHandle<JSArray>();
}
@ -2207,7 +2225,11 @@ BUILTIN(DateConstructor) {
char buffer[128];
Vector<char> str(buffer, arraysize(buffer));
ToDateString(time_val, str, isolate->date_cache());
return *isolate->factory()->NewStringFromAsciiChecked(str.start());
Handle<String> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
return *result;
}
@ -2787,7 +2809,11 @@ BUILTIN(DatePrototypeToDateString) {
char buffer[128];
Vector<char> str(buffer, arraysize(buffer));
ToDateString(date->value()->Number(), str, isolate->date_cache(), kDateOnly);
return *isolate->factory()->NewStringFromAsciiChecked(str.start());
Handle<String> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
return *result;
}
@ -2827,7 +2853,11 @@ BUILTIN(DatePrototypeToString) {
char buffer[128];
Vector<char> str(buffer, arraysize(buffer));
ToDateString(date->value()->Number(), str, isolate->date_cache());
return *isolate->factory()->NewStringFromAsciiChecked(str.start());
Handle<String> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
return *result;
}
@ -2838,7 +2868,11 @@ BUILTIN(DatePrototypeToTimeString) {
char buffer[128];
Vector<char> str(buffer, arraysize(buffer));
ToDateString(date->value()->Number(), str, isolate->date_cache(), kTimeOnly);
return *isolate->factory()->NewStringFromAsciiChecked(str.start());
Handle<String> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
return *result;
}

10
deps/v8/src/compiler/pipeline.cc

@ -677,6 +677,13 @@ struct SimplifiedLoweringPhase {
SimplifiedLowering lowering(data->jsgraph(), temp_zone,
data->source_positions());
lowering.LowerAllNodes();
// TODO(bmeurer): See comment on SimplifiedLowering::abort_compilation_.
if (lowering.abort_compilation_) {
data->set_compilation_failed();
return;
}
JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common());
@ -1204,6 +1211,9 @@ Handle<Code> Pipeline::GenerateCode() {
// Kill the Typer and thereby uninstall the decorator (if any).
typer.Reset(nullptr);
// TODO(bmeurer): See comment on SimplifiedLowering::abort_compilation_.
if (data.compilation_failed()) return Handle<Code>::null();
return ScheduleAndGenerateCode(
Linkage::ComputeIncoming(data.instruction_zone(), info()));
}

8
deps/v8/src/compiler/simplified-lowering.cc

@ -1189,10 +1189,18 @@ class RepresentationSelector {
NodeOutputInfo(access.machine_type().representation(),
NodeProperties::GetType(node));
} else {
if (access.machine_type().representation() !=
MachineRepresentation::kFloat64) {
// TODO(bmeurer): See comment on abort_compilation_.
if (lower()) lowering->abort_compilation_ = true;
}
output_info = NodeOutputInfo::Float64();
}
}
} else {
// TODO(bmeurer): See comment on abort_compilation_.
if (lower()) lowering->abort_compilation_ = true;
// If undefined is not truncated away, we need to have the tagged
// representation.
output_info = NodeOutputInfo::AnyTagged();

5
deps/v8/src/compiler/simplified-lowering.h

@ -43,6 +43,11 @@ class SimplifiedLowering final {
void DoStringLessThan(Node* node);
void DoStringLessThanOrEqual(Node* node);
// TODO(bmeurer): This is a gigantic hack to support the gigantic LoadBuffer
// typing hack to support the gigantic "asm.js should be fast without proper
// verifier"-hack, ... Kill this! Soon! Really soon! I'm serious!
bool abort_compilation_ = false;
private:
JSGraph* const jsgraph_;
Zone* const zone_;

37
deps/v8/src/elements.cc

@ -545,6 +545,16 @@ class ElementsAccessorBase : public ElementsAccessor {
*holder, *backing_store, index, filter) != kMaxUInt32;
}
bool HasAccessors(JSObject* holder) final {
return ElementsAccessorSubclass::HasAccessorsImpl(holder,
holder->elements());
}
static bool HasAccessorsImpl(JSObject* holder,
FixedArrayBase* backing_store) {
return false;
}
Handle<Object> Get(Handle<FixedArrayBase> backing_store,
uint32_t entry) final {
return ElementsAccessorSubclass::GetImpl(backing_store, entry);
@ -1048,6 +1058,21 @@ class DictionaryElementsAccessor
obj->set_elements(*new_elements);
}
static bool HasAccessorsImpl(JSObject* holder,
FixedArrayBase* backing_store) {
SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store);
if (!dict->requires_slow_elements()) return false;
int capacity = dict->Capacity();
for (int i = 0; i < capacity; i++) {
Object* key = dict->KeyAt(i);
if (!dict->IsKey(key)) continue;
DCHECK(!dict->IsDeleted(i));
PropertyDetails details = dict->DetailsAt(i);
if (details.type() == ACCESSOR_CONSTANT) return true;
}
return false;
}
static Object* GetRaw(FixedArrayBase* store, uint32_t entry) {
SeededNumberDictionary* backing_store = SeededNumberDictionary::cast(store);
return backing_store->ValueAt(entry);
@ -1813,6 +1838,11 @@ class TypedElementsAccessor
BackingStore::cast(backing_store)->SetValue(entry, value);
}
static bool HasAccessorsImpl(JSObject* holder,
FixedArrayBase* backing_store) {
return false;
}
static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry,
Object* value, WriteBarrierMode mode) {
BackingStore::cast(backing_store)->SetValue(entry, value);
@ -1970,6 +2000,13 @@ class SloppyArgumentsElementsAccessor
return ArgumentsAccessor::HasEntryImpl(arguments, entry - length);
}
static bool HasAccessorsImpl(JSObject* holder,
FixedArrayBase* backing_store) {
FixedArray* parameter_map = FixedArray::cast(backing_store);
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
return ArgumentsAccessor::HasAccessorsImpl(holder, arguments);
}
static uint32_t GetIndexForEntryImpl(FixedArrayBase* parameters,
uint32_t entry) {
FixedArray* parameter_map = FixedArray::cast(parameters);

2
deps/v8/src/elements.h

@ -54,6 +54,8 @@ class ElementsAccessor {
return HasElement(holder, index, handle(holder->elements()), filter);
}
virtual bool HasAccessors(JSObject* holder) = 0;
// Returns true if the backing store is compact in the given range
virtual bool IsPacked(Handle<JSObject> holder,
Handle<FixedArrayBase> backing_store, uint32_t start,

13
deps/v8/src/heap/incremental-marking.cc

@ -847,16 +847,21 @@ void IncrementalMarking::MarkObject(Heap* heap, HeapObject* obj) {
intptr_t IncrementalMarking::ProcessMarkingDeque(intptr_t bytes_to_process) {
intptr_t bytes_processed = 0;
Map* filler_map = heap_->one_pointer_filler_map();
Map* one_pointer_filler_map = heap_->one_pointer_filler_map();
Map* two_pointer_filler_map = heap_->two_pointer_filler_map();
MarkingDeque* marking_deque =
heap_->mark_compact_collector()->marking_deque();
while (!marking_deque->IsEmpty() && bytes_processed < bytes_to_process) {
HeapObject* obj = marking_deque->Pop();
// Explicitly skip one word fillers. Incremental markbit patterns are
// correct only for objects that occupy at least two words.
// Explicitly skip one and two word fillers. Incremental markbit patterns
// are correct only for objects that occupy at least two words.
// Moreover, slots filtering for left-trimmed arrays works only when
// the distance between the old array start and the new array start
// is greater than two if both starts are marked.
Map* map = obj->map();
if (map == filler_map) continue;
if (map == one_pointer_filler_map || map == two_pointer_filler_map)
continue;
int size = obj->SizeFromMap(map);
unscanned_bytes_of_large_object_ = 0;

7
deps/v8/src/heap/memory-reducer.cc

@ -73,14 +73,7 @@ void MemoryReducer::NotifyTimer(const Event& event) {
PrintIsolate(heap()->isolate(), "Memory reducer: started GC #%d\n",
state_.started_gcs);
}
if (heap()->ShouldOptimizeForMemoryUsage()) {
// TODO(ulan): Remove this once crbug.com/552305 is fixed.
// Do full GC if memory usage has higher priority than latency.
heap()->CollectAllGarbage(Heap::kReduceMemoryFootprintMask,
"memory reducer");
} else {
heap()->StartIdleIncrementalMarking();
}
} else if (state_.action == kWait) {
if (!heap()->incremental_marking()->IsStopped() &&
heap()->ShouldOptimizeForMemoryUsage()) {

6
deps/v8/src/runtime/runtime-array.cc

@ -120,9 +120,11 @@ RUNTIME_FUNCTION(Runtime_PushIfAbsent) {
RUNTIME_FUNCTION(Runtime_RemoveArrayHoles) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
return *JSObject::PrepareElementsForSort(object, limit);
if (object->IsJSProxy()) return Smi::FromInt(-1);
return *JSObject::PrepareElementsForSort(Handle<JSObject>::cast(object),
limit);
}

1
deps/v8/test/cctest/cctest.gyp

@ -81,7 +81,6 @@
'compiler/test-run-jsops.cc',
'compiler/test-run-machops.cc',
'compiler/test-run-native-calls.cc',
'compiler/test-run-properties.cc',
'compiler/test-run-stackcheck.cc',
'compiler/test-run-stubs.cc',
'compiler/test-run-variables.cc',

142
deps/v8/test/cctest/compiler/test-run-properties.cc

@ -1,142 +0,0 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "test/cctest/compiler/function-tester.h"
namespace v8 {
namespace internal {
namespace compiler {
template <typename U>
static void TypedArrayLoadHelper(const char* array_type) {
static const uint32_t kValues[] = {
0x00000000, 0x00000001, 0x00000023, 0x00000042, 0x12345678, 0x87654321,
0x0000003f, 0x0000007f, 0x00003fff, 0x00007fff, 0x3fffffff, 0x7fffffff,
0x000000ff, 0x00000080, 0x0000ffff, 0x00008000, 0xffffffff, 0x80000000};
EmbeddedVector<char, 1024> values_buffer;
StringBuilder values_builder(values_buffer.start(), values_buffer.length());
for (size_t i = 0; i < arraysize(kValues); ++i) {
values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
}
// Note that below source creates two different typed arrays with the same
// elements kind to get coverage for both (on heap / with external backing
// store) access patterns.
const char* source =
"(function(a) {"
" var x = (a = new %sArray(%d)); %s;"
" var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
" if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
" if (!%%HasFixed%sElements(y)) %%AbortJS('y');"
" function f(a,b) {"
" a = a | 0; b = b | 0;"
" return x[a] + y[b];"
" }"
" return f;"
"})()";
EmbeddedVector<char, 1024> source_buffer;
SNPrintF(source_buffer, source, array_type, arraysize(kValues),
values_buffer.start(), array_type, arraysize(kValues),
values_buffer.start(), array_type, array_type);
FunctionTester T(source_buffer.start(),
CompilationInfo::kFunctionContextSpecializing |
CompilationInfo::kTypingEnabled);
for (size_t i = 0; i < arraysize(kValues); ++i) {
for (size_t j = 0; j < arraysize(kValues); ++j) {
volatile U value_a = static_cast<U>(kValues[i]);
volatile U value_b = static_cast<U>(kValues[j]);
double expected =
static_cast<double>(value_a) + static_cast<double>(value_b);
T.CheckCall(T.Val(expected), T.Val(static_cast<double>(i)),
T.Val(static_cast<double>(j)));
}
}
}
TEST(TypedArrayLoad) {
FLAG_typed_array_max_size_in_heap = 256;
TypedArrayLoadHelper<int8_t>("Int8");
TypedArrayLoadHelper<uint8_t>("Uint8");
TypedArrayLoadHelper<int16_t>("Int16");
TypedArrayLoadHelper<uint16_t>("Uint16");
TypedArrayLoadHelper<int32_t>("Int32");
TypedArrayLoadHelper<uint32_t>("Uint32");
TypedArrayLoadHelper<float>("Float32");
TypedArrayLoadHelper<double>("Float64");
// TODO(mstarzinger): Add tests for ClampedUint8.
}
template <typename U>
static void TypedArrayStoreHelper(const char* array_type) {
static const uint32_t kValues[] = {
0x00000000, 0x00000001, 0x00000023, 0x00000042, 0x12345678, 0x87654321,
0x0000003f, 0x0000007f, 0x00003fff, 0x00007fff, 0x3fffffff, 0x7fffffff,
0x000000ff, 0x00000080, 0x0000ffff, 0x00008000, 0xffffffff, 0x80000000};
EmbeddedVector<char, 1024> values_buffer;
StringBuilder values_builder(values_buffer.start(), values_buffer.length());
for (size_t i = 0; i < arraysize(kValues); ++i) {
values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
}
// Note that below source creates two different typed arrays with the same
// elements kind to get coverage for both (on heap/with external backing
// store) access patterns.
const char* source =
"(function(a) {"
" var x = (a = new %sArray(%d)); %s;"
" var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
" if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
" if (!%%HasFixed%sElements(y)) %%AbortJS('y');"
" function f(a,b) {"
" a = a | 0; b = b | 0;"
" var t = x[a];"
" x[a] = y[b];"
" y[b] = t;"
" t = y[b];"
" y[b] = x[a];"
" x[a] = t;"
" return x[a] + y[b];"
" }"
" return f;"
"})()";
EmbeddedVector<char, 2048> source_buffer;
SNPrintF(source_buffer, source, array_type, arraysize(kValues),
values_buffer.start(), array_type, arraysize(kValues),
values_buffer.start(), array_type, array_type);
FunctionTester T(source_buffer.start(),
CompilationInfo::kFunctionContextSpecializing |
CompilationInfo::kTypingEnabled);
for (size_t i = 0; i < arraysize(kValues); ++i) {
for (size_t j = 0; j < arraysize(kValues); ++j) {
volatile U value_a = static_cast<U>(kValues[i]);
volatile U value_b = static_cast<U>(kValues[j]);
double expected =
static_cast<double>(value_a) + static_cast<double>(value_b);
T.CheckCall(T.Val(expected), T.Val(static_cast<double>(i)),
T.Val(static_cast<double>(j)));
}
}
}
TEST(TypedArrayStore) {
FLAG_typed_array_max_size_in_heap = 256;
TypedArrayStoreHelper<int8_t>("Int8");
TypedArrayStoreHelper<uint8_t>("Uint8");
TypedArrayStoreHelper<int16_t>("Int16");
TypedArrayStoreHelper<uint16_t>("Uint16");
TypedArrayStoreHelper<int32_t>("Int32");
TypedArrayStoreHelper<uint32_t>("Uint32");
TypedArrayStoreHelper<float>("Float32");
TypedArrayStoreHelper<double>("Float64");
// TODO(mstarzinger): Add tests for ClampedUint8.
}
} // namespace compiler
} // namespace internal
} // namespace v8

13
deps/v8/test/mjsunit/array-concat.js

@ -29,6 +29,19 @@
* @fileoverview Test concat on small and large arrays
*/
(function testStringWrapperConcat() {
var concat = Array.prototype.concat;
var str = new String('abcd');
assertEquals([1,2,3,new String('abcd')], [1, 2, 3].concat(str));
assertEquals([new String("abcd")], concat.call(str));
var array = [1, 2, 3];
array.__proto__ = str;
array.length = 4;
assertEquals([1,2,3,'d'], concat.call(array));
})()
var poses;
poses = [140, 4000000000];

6
deps/v8/test/mjsunit/array-sort.js

@ -464,3 +464,9 @@ function TestSortToObject() {
assertEquals(0, Number(Array.prototype.sort.call(0)));
}
TestSortToObject();
function TestSortOnProxy() {
var p = new Proxy([2,1,3], {});
assertEquals([1,2,3], p.sort());
}
TestSortOnProxy();

76
deps/v8/test/mjsunit/regress/regress-4800.js

@ -0,0 +1,76 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
function f(x, len) {
var distraction = [];
var result = new Array(25);
// Create a bunch of double values with long live ranges.
var d0 = x + 0.5;
var d1 = x + 1.5;
var d2 = x + 2.5;
var d3 = x + 3.5;
var d4 = x + 4.5;
var d5 = x + 5.5;
var d6 = x + 6.5;
var d7 = x + 7.5;
var d8 = x + 8.5;
var d9 = x + 9.5;
var d10 = x + 10.5;
var d11 = x + 11.5;
var d12 = x + 12.5;
var d13 = x + 13.5;
var d14 = x + 14.5;
var d15 = x + 15.5;
var d16 = x + 16.5;
var d17 = x + 17.5;
var d18 = x + 18.5;
var d19 = x + 19.5;
var d20 = x + 20.5;
var d21 = x + 21.5;
var d22 = x + 22.5;
var d23 = x + 23.5;
var d24 = x + 24.5;
// Trigger a stub failure when the array grows too big.
distraction[len] = 0;
// Write the long-lived doubles to memory and verify them.
result[0] = d0;
result[1] = d1;
result[2] = d2;
result[3] = d3;
result[4] = d4;
result[5] = d5;
result[6] = d6;
result[7] = d7;
result[8] = d8;
result[9] = d9;
result[10] = d10;
result[11] = d11;
result[12] = d12;
result[13] = d13;
result[14] = d14;
result[15] = d15;
result[16] = d16;
result[17] = d17;
result[18] = d18;
result[19] = d19;
result[20] = d20;
result[21] = d21;
result[22] = d22;
result[23] = d23;
result[24] = d24;
for (var i = 0; i < result.length; i++) {
assertEquals(x + i + 0.5, result[i]);
}
}
f(0, 10);
f(0, 10);
%OptimizeFunctionOnNextCall(f);
f(0, 80000);

20
deps/v8/test/mjsunit/regress/regress-crbug-589792.js

@ -0,0 +1,20 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var boom = (function(stdlib, foreign, heap) {
"use asm";
var MEM8 = new stdlib.Uint8Array(heap);
var MEM32 = new stdlib.Int32Array(heap);
function foo(i, j) {
j = MEM8[256];
// This following value '10' determines the value of 'rax'
MEM32[j >> 10] = 0xabcdefaa;
return MEM32[j >> 2] + j
}
return foo
})(this, 0, new ArrayBuffer(256));
%OptimizeFunctionOnNextCall(boom);
boom(0, 0x1000);

36
deps/v8/test/mjsunit/regress/regress-crbug-594574-concat-leak-1.js

@ -0,0 +1,36 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-gc
array = new Array(10);
array[0] = 0.1;
// array[1] = THE_HOLE, reading through the prototype chain
array[2] = 2.1;
array[3] = 3.1;
var copy = array.slice(0, array.length);
// Change the array's prototype.
var proto = {};
array.__proto__ = proto;
// Define [1] on the prototype to alter the array during concatenation.
Object.defineProperty(
proto, 1, {
get() {
// Alter the array.
array.length = 1;
// Force gc to move the array.
gc();
return "value from proto";
},
set(new_value) { }
});
var concatted_array = Array.prototype.concat.call(array);
assertEquals(concatted_array[0], 0.1);
assertEquals(concatted_array[1], "value from proto");
assertEquals(concatted_array[2], undefined);
assertEquals(concatted_array[3], undefined);

35
deps/v8/test/mjsunit/regress/regress-crbug-594574-concat-leak-2.js

@ -0,0 +1,35 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-gc
array = new Array(10);
array[0] = 0.1;
// array[1] = THE_HOLE, reading through the prototype chain
array[2] = 2.1;
array[3] = 3.1;
var copy = array.slice(0, array.length);
// Use the defaul array prototype.
var proto = array.__proto__;
// Define [1] on the prototype to alter the array during concatenation.
Object.defineProperty(
proto, 1, {
get() {
// Alter the array.
array.length = 1;
// Force gc to move the array.
gc();
return "value from proto";
},
set(new_value) { }
});
var concatted_array = Array.prototype.concat.call(array);
assertEquals(concatted_array[0], 0.1);
assertEquals(concatted_array[1], "value from proto");
assertEquals(concatted_array[2], undefined);
assertEquals(concatted_array[3], undefined);
Loading…
Cancel
Save