Version 3.24.18
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@18654 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 2792975..530ac97 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,9 @@
-2014-01-16: Version 3.24.17
+2014-01-17: Version 3.24.18
- Make it possible to compile d8 for the host toolset as well (issue
- 1775).
+ Performance and stability improvements on all platforms.
+
+
+2014-01-16: Version 3.24.17
Make cells pointing to JSObjects weak in optimized code (issue 2073).
diff --git a/include/v8.h b/include/v8.h
index 414fe6c..8f19498 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -5394,7 +5394,7 @@
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
- static const int kEmptyStringRootIndex = 136;
+ static const int kEmptyStringRootIndex = 145;
static const int kNodeClassIdOffset = 1 * kApiPointerSize;
static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
@@ -5405,7 +5405,7 @@
static const int kNodeIsIndependentShift = 4;
static const int kNodeIsPartiallyDependentShift = 5;
- static const int kJSObjectType = 0xb2;
+ static const int kJSObjectType = 0xbb;
static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83;
static const int kForeignType = 0x87;
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 470469f..a860293 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -2110,7 +2110,7 @@
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
- if (!instr->is_external()) {
+ if (!instr->is_typed_elements()) {
LOperand* obj = NULL;
if (instr->representation().IsDouble()) {
obj = UseRegister(instr->elements());
@@ -2122,20 +2122,19 @@
} else {
ASSERT(
(instr->representation().IsInteger32() &&
- (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
- (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+ !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->representation().IsDouble() &&
- ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
- (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
- LOperand* external_pointer = UseRegister(instr->elements());
- result = new(zone()) LLoadKeyed(external_pointer, key);
+ IsDoubleOrFloatElementsKind(instr->elements_kind())));
+ LOperand* backing_store = UseRegister(instr->elements());
+ result = new(zone()) LLoadKeyed(backing_store, key);
}
DefineAsRegister(result);
// An unsigned int array load might overflow and cause a deopt, make sure it
// has an environment.
bool can_deoptimize = instr->RequiresHoleCheck() ||
- (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
+ elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS ||
+ elements_kind == UINT32_ELEMENTS;
return can_deoptimize ? AssignEnvironment(result) : result;
}
@@ -2152,7 +2151,7 @@
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
- if (!instr->is_external()) {
+ if (!instr->is_typed_elements()) {
ASSERT(instr->elements()->representation().IsTagged());
bool needs_write_barrier = instr->NeedsWriteBarrier();
LOperand* object = NULL;
@@ -2181,16 +2180,17 @@
ASSERT(
(instr->value()->representation().IsInteger32() &&
- (instr->elements_kind() != EXTERNAL_FLOAT_ELEMENTS) &&
- (instr->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS)) ||
+ !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->value()->representation().IsDouble() &&
- ((instr->elements_kind() == EXTERNAL_FLOAT_ELEMENTS) ||
- (instr->elements_kind() == EXTERNAL_DOUBLE_ELEMENTS))));
- ASSERT(instr->elements()->representation().IsExternal());
+ IsDoubleOrFloatElementsKind(instr->elements_kind())));
+ ASSERT((instr->is_fixed_typed_array() &&
+ instr->elements()->representation().IsTagged()) ||
+ (instr->is_external() &&
+ instr->elements()->representation().IsExternal()));
LOperand* val = UseRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
- LOperand* external_pointer = UseRegister(instr->elements());
- return new(zone()) LStoreKeyed(external_pointer, key, val);
+ LOperand* backing_store = UseRegister(instr->elements());
+ return new(zone()) LStoreKeyed(backing_store, key, val);
}
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 2cb4ff4..ddff815 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -1595,6 +1595,12 @@
bool is_external() const {
return hydrogen()->is_external();
}
+ bool is_fixed_typed_array() const {
+ return hydrogen()->is_fixed_typed_array();
+ }
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@@ -2227,6 +2233,12 @@
}
bool is_external() const { return hydrogen()->is_external(); }
+ bool is_fixed_typed_array() const {
+ return hydrogen()->is_fixed_typed_array();
+ }
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index ae9aae3..2ea6f7c 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -720,7 +720,6 @@
LInstruction* instr,
SafepointMode safepoint_mode,
TargetAddressStorageMode storage_mode) {
- EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
ASSERT(instr != NULL);
// Block literal pool emission to ensure nop indicating no inlined smi code
// is in the correct position.
@@ -3221,20 +3220,28 @@
int element_size_shift = ElementsKindToShiftSize(elements_kind);
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
- int additional_offset = instr->additional_index() << element_size_shift;
+ int additional_offset = IsFixedTypedArrayElementsKind(elements_kind)
+ ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
+ : 0;
+
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
- elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+ elements_kind == FLOAT32_ELEMENTS ||
+ elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
+ elements_kind == FLOAT64_ELEMENTS) {
+ int base_offset =
+ (instr->additional_index() << element_size_shift) + additional_offset;
DwVfpRegister result = ToDoubleRegister(instr->result());
Operand operand = key_is_constant
? Operand(constant_key << element_size_shift)
: Operand(key, LSL, shift_size);
__ add(scratch0(), external_pointer, operand);
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
- __ vldr(double_scratch0().low(), scratch0(), additional_offset);
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS) {
+ __ vldr(double_scratch0().low(), scratch0(), base_offset);
__ vcvt_f64_f32(result, double_scratch0().low());
- } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
- __ vldr(result, scratch0(), additional_offset);
+ } else { // loading doubles, not floats.
+ __ vldr(result, scratch0(), base_offset);
}
} else {
Register result = ToRegister(instr->result());
@@ -3244,28 +3251,37 @@
instr->additional_index(), additional_offset);
switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
+ case INT8_ELEMENTS:
__ ldrsb(result, mem_operand);
break;
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
__ ldrb(result, mem_operand);
break;
case EXTERNAL_SHORT_ELEMENTS:
+ case INT16_ELEMENTS:
__ ldrsh(result, mem_operand);
break;
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case UINT16_ELEMENTS:
__ ldrh(result, mem_operand);
break;
case EXTERNAL_INT_ELEMENTS:
+ case INT32_ELEMENTS:
__ ldr(result, mem_operand);
break;
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case UINT32_ELEMENTS:
__ ldr(result, mem_operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ cmp(result, Operand(0x80000000));
DeoptimizeIf(cs, instr->environment());
}
break;
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
@@ -3363,7 +3379,7 @@
void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
- if (instr->is_external()) {
+ if (instr->is_typed_elements()) {
DoLoadKeyedExternalArray(instr);
} else if (instr->hydrogen()->representation().IsDouble()) {
DoLoadKeyedFixedDoubleArray(instr);
@@ -3381,14 +3397,26 @@
int shift_size,
int additional_index,
int additional_offset) {
- if (additional_index != 0 && !key_is_constant) {
- additional_index *= 1 << (element_size - shift_size);
- __ add(scratch0(), key, Operand(additional_index));
- }
-
+ int base_offset = (additional_index << element_size) + additional_offset;
if (key_is_constant) {
return MemOperand(base,
- (constant_key << element_size) + additional_offset);
+ base_offset + (constant_key << element_size));
+ }
+
+ if (additional_offset != 0) {
+ __ mov(scratch0(), Operand(base_offset));
+ if (shift_size >= 0) {
+ __ add(scratch0(), scratch0(), Operand(key, LSL, shift_size));
+ } else {
+ ASSERT_EQ(-1, shift_size);
+ __ add(scratch0(), scratch0(), Operand(key, LSR, 1));
+ }
+ return MemOperand(base, scratch0());
+ }
+
+ if (additional_index != 0) {
+ additional_index *= 1 << (element_size - shift_size);
+ __ add(scratch0(), key, Operand(additional_index));
}
if (additional_index == 0) {
@@ -4256,10 +4284,16 @@
int element_size_shift = ElementsKindToShiftSize(elements_kind);
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
- int additional_offset = instr->additional_index() << element_size_shift;
+ int additional_offset = IsFixedTypedArrayElementsKind(elements_kind)
+ ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
+ : 0;
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
- elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+ elements_kind == FLOAT32_ELEMENTS ||
+ elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
+ elements_kind == FLOAT64_ELEMENTS) {
+ int base_offset =
+ (instr->additional_index() << element_size_shift) + additional_offset;
Register address = scratch0();
DwVfpRegister value(ToDoubleRegister(instr->value()));
if (key_is_constant) {
@@ -4272,11 +4306,12 @@
} else {
__ add(address, external_pointer, Operand(key, LSL, shift_size));
}
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS) {
__ vcvt_f32_f64(double_scratch0().low(), value);
- __ vstr(double_scratch0().low(), address, additional_offset);
- } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
- __ vstr(value, address, additional_offset);
+ __ vstr(double_scratch0().low(), address, base_offset);
+ } else { // Storing doubles, not floats.
+ __ vstr(value, address, base_offset);
}
} else {
Register value(ToRegister(instr->value()));
@@ -4288,16 +4323,25 @@
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
+ case INT8_ELEMENTS:
__ strb(value, mem_operand);
break;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT16_ELEMENTS:
__ strh(value, mem_operand);
break;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case INT32_ELEMENTS:
+ case UINT32_ELEMENTS:
__ str(value, mem_operand);
break;
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@@ -4407,7 +4451,7 @@
void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
// By cases: external, fast double
- if (instr->is_external()) {
+ if (instr->is_typed_elements()) {
DoStoreKeyedExternalArray(instr);
} else if (instr->hydrogen()->value()->representation().IsDouble()) {
DoStoreKeyedFixedDoubleArray(instr);
@@ -5579,26 +5623,27 @@
void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
- if (info()->IsStub()) return;
- // Ensure that we have enough space after the previous lazy-bailout
- // instruction for patching the code here.
- int current_pc = masm()->pc_offset();
- if (current_pc < last_lazy_deopt_pc_ + space_needed) {
- // Block literal pool emission for duration of padding.
- Assembler::BlockConstPoolScope block_const_pool(masm());
- int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
- ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
- while (padding_size > 0) {
- __ nop();
- padding_size -= Assembler::kInstrSize;
+ if (!info()->IsStub()) {
+ // Ensure that we have enough space after the previous lazy-bailout
+ // instruction for patching the code here.
+ int current_pc = masm()->pc_offset();
+ if (current_pc < last_lazy_deopt_pc_ + space_needed) {
+ // Block literal pool emission for duration of padding.
+ Assembler::BlockConstPoolScope block_const_pool(masm());
+ int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
+ ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
+ while (padding_size > 0) {
+ __ nop();
+ padding_size -= Assembler::kInstrSize;
+ }
}
}
+ last_lazy_deopt_pc_ = masm()->pc_offset();
}
void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
- last_lazy_deopt_pc_ = masm()->pc_offset();
ASSERT(instr->HasEnvironment());
LEnvironment* env = instr->environment();
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
@@ -5673,7 +5718,6 @@
RelocInfo::CODE_TARGET,
instr);
EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
- last_lazy_deopt_pc_ = masm()->pc_offset();
__ bind(&done);
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
@@ -5686,7 +5730,6 @@
__ cmp(sp, Operand(ip));
__ b(lo, deferred_stack_check->entry());
EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
- last_lazy_deopt_pc_ = masm()->pc_offset();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index d039ac0..288cac2 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -102,9 +102,7 @@
void Bootstrapper::InitializeOncePerProcess() {
-#ifdef ADDRESS_SANITIZER
FreeBufferExtension::Register();
-#endif
GCExtension::Register();
ExternalizeStringExtension::Register();
StatisticsExtension::Register();
@@ -238,13 +236,18 @@
// provided.
static bool InstallExtensions(Handle<Context> native_context,
v8::ExtensionConfiguration* extensions);
+ static bool InstallAutoExtensions(Isolate* isolate,
+ ExtensionStates* extension_states);
+ static bool InstallRequestedExtensions(Isolate* isolate,
+ v8::ExtensionConfiguration* extensions,
+ ExtensionStates* extension_states);
static bool InstallExtension(Isolate* isolate,
const char* name,
ExtensionStates* extension_states);
static bool InstallExtension(Isolate* isolate,
v8::RegisteredExtension* current,
ExtensionStates* extension_states);
- static void InstallSpecialObjects(Handle<Context> native_context);
+ static bool InstallSpecialObjects(Handle<Context> native_context);
bool InstallJSBuiltins(Handle<JSBuiltinsObject> builtins);
bool ConfigureApiObject(Handle<JSObject> object,
Handle<ObjectTemplateInfo> object_template);
@@ -2152,13 +2155,12 @@
BootstrapperActive active(this);
SaveContext saved_context(isolate_);
isolate_->set_context(*native_context);
- if (!Genesis::InstallExtensions(native_context, extensions)) return false;
- Genesis::InstallSpecialObjects(native_context);
- return true;
+ return Genesis::InstallExtensions(native_context, extensions) &&
+ Genesis::InstallSpecialObjects(native_context);
}
-void Genesis::InstallSpecialObjects(Handle<Context> native_context) {
+bool Genesis::InstallSpecialObjects(Handle<Context> native_context) {
Isolate* isolate = native_context->GetIsolate();
Factory* factory = isolate->factory();
HandleScope scope(isolate);
@@ -2168,11 +2170,9 @@
if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) {
Handle<String> natives =
factory->InternalizeUtf8String(FLAG_expose_natives_as);
- CHECK_NOT_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
- global, natives,
- Handle<JSObject>(global->builtins()),
- DONT_ENUM));
+ JSObject::SetLocalPropertyIgnoreAttributes(
+ global, natives, Handle<JSObject>(global->builtins()), DONT_ENUM);
+ if (isolate->has_pending_exception()) return false;
}
Handle<Object> Error = GetProperty(global, "Error");
@@ -2181,10 +2181,9 @@
STATIC_ASCII_VECTOR("stackTraceLimit"));
Handle<Smi> stack_trace_limit(
Smi::FromInt(FLAG_stack_trace_limit), isolate);
- CHECK_NOT_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
- Handle<JSObject>::cast(Error), name,
- stack_trace_limit, NONE));
+ JSObject::SetLocalPropertyIgnoreAttributes(
+ Handle<JSObject>::cast(Error), name, stack_trace_limit, NONE);
+ if (isolate->has_pending_exception()) return false;
}
#ifdef ENABLE_DEBUGGER_SUPPORT
@@ -2193,7 +2192,7 @@
Debug* debug = isolate->debug();
// If loading fails we just bail out without installing the
// debugger but without tanking the whole context.
- if (!debug->Load()) return;
+ if (!debug->Load()) return true;
// Set the security token for the debugger context to the same as
// the shell native context to allow calling between these (otherwise
// exposing debug global object doesn't make much sense).
@@ -2204,11 +2203,12 @@
factory->InternalizeUtf8String(FLAG_expose_debug_as);
Handle<Object> global_proxy(
debug->debug_context()->global_proxy(), isolate);
- CHECK_NOT_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
- global, debug_string, global_proxy, DONT_ENUM));
+ JSObject::SetLocalPropertyIgnoreAttributes(
+ global, debug_string, global_proxy, DONT_ENUM);
+ if (isolate->has_pending_exception()) return false;
}
#endif
+ return true;
}
@@ -2240,38 +2240,46 @@
reinterpret_cast<void*>(static_cast<intptr_t>(state));
}
+
bool Genesis::InstallExtensions(Handle<Context> native_context,
v8::ExtensionConfiguration* extensions) {
Isolate* isolate = native_context->GetIsolate();
ExtensionStates extension_states; // All extensions have state UNVISITED.
- // Install auto extensions.
- v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
- while (current != NULL) {
- if (current->extension()->auto_enable())
- InstallExtension(isolate, current, &extension_states);
- current = current->next();
- }
+ return InstallAutoExtensions(isolate, &extension_states) &&
+ (!FLAG_expose_free_buffer ||
+ InstallExtension(isolate, "v8/free-buffer", &extension_states)) &&
+ (!FLAG_expose_gc ||
+ InstallExtension(isolate, "v8/gc", &extension_states)) &&
+ (!FLAG_expose_externalize_string ||
+ InstallExtension(isolate, "v8/externalize", &extension_states)) &&
+ (!FLAG_track_gc_object_stats ||
+ InstallExtension(isolate, "v8/statistics", &extension_states)) &&
+ (!FLAG_expose_trigger_failure ||
+ InstallExtension(isolate, "v8/trigger-failure", &extension_states)) &&
+ InstallRequestedExtensions(isolate, extensions, &extension_states);
+}
-#ifdef ADDRESS_SANITIZER
- if (FLAG_expose_free_buffer) {
- InstallExtension(isolate, "v8/free-buffer", &extension_states);
- }
-#endif
- if (FLAG_expose_gc) InstallExtension(isolate, "v8/gc", &extension_states);
- if (FLAG_expose_externalize_string) {
- InstallExtension(isolate, "v8/externalize", &extension_states);
- }
- if (FLAG_track_gc_object_stats) {
- InstallExtension(isolate, "v8/statistics", &extension_states);
- }
- if (FLAG_expose_trigger_failure) {
- InstallExtension(isolate, "v8/trigger-failure", &extension_states);
- }
+bool Genesis::InstallAutoExtensions(Isolate* isolate,
+ ExtensionStates* extension_states) {
+ for (v8::RegisteredExtension* it = v8::RegisteredExtension::first_extension();
+ it != NULL;
+ it = it->next()) {
+ if (it->extension()->auto_enable() &&
+ !InstallExtension(isolate, it, extension_states)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+bool Genesis::InstallRequestedExtensions(Isolate* isolate,
+ v8::ExtensionConfiguration* extensions,
+ ExtensionStates* extension_states) {
for (const char** it = extensions->begin(); it != extensions->end(); ++it) {
- if (!InstallExtension(isolate, *it, &extension_states)) return false;
+ if (!InstallExtension(isolate, *it, extension_states)) return false;
}
-
return true;
}
@@ -2281,19 +2289,16 @@
bool Genesis::InstallExtension(Isolate* isolate,
const char* name,
ExtensionStates* extension_states) {
- v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
- // Loop until we find the relevant extension
- while (current != NULL) {
- if (strcmp(name, current->extension()->name()) == 0) break;
- current = current->next();
+ for (v8::RegisteredExtension* it = v8::RegisteredExtension::first_extension();
+ it != NULL;
+ it = it->next()) {
+ if (strcmp(name, it->extension()->name()) == 0) {
+ return InstallExtension(isolate, it, extension_states);
+ }
}
- // Didn't find the extension; fail.
- if (!Utils::ApiCheck(current != NULL,
- "v8::Context::New()",
- "Cannot find required extension")) {
- return false;
- }
- return InstallExtension(isolate, current, extension_states);
+ return Utils::ApiCheck(false,
+ "v8::Context::New()",
+ "Cannot find required extension");
}
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 76af3f7..7e88675 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -570,6 +570,15 @@
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
UNREACHABLE();
break;
case DICTIONARY_ELEMENTS:
diff --git a/src/elements-kind.cc b/src/elements-kind.cc
index 689c220..ebb4616 100644
--- a/src/elements-kind.cc
+++ b/src/elements-kind.cc
@@ -40,17 +40,26 @@
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
return 0;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
return 1;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
return 2;
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
+ case FLOAT64_ELEMENTS:
return 3;
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
diff --git a/src/elements-kind.h b/src/elements-kind.h
index 51a6902..3d55105 100644
--- a/src/elements-kind.h
+++ b/src/elements-kind.h
@@ -63,13 +63,26 @@
EXTERNAL_DOUBLE_ELEMENTS,
EXTERNAL_PIXEL_ELEMENTS,
+ // Fixed typed arrays
+ UINT8_ELEMENTS,
+ INT8_ELEMENTS,
+ UINT16_ELEMENTS,
+ INT16_ELEMENTS,
+ UINT32_ELEMENTS,
+ INT32_ELEMENTS,
+ FLOAT32_ELEMENTS,
+ FLOAT64_ELEMENTS,
+ UINT8_CLAMPED_ELEMENTS,
+
// Derived constants from ElementsKind
FIRST_ELEMENTS_KIND = FAST_SMI_ELEMENTS,
- LAST_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS,
+ LAST_ELEMENTS_KIND = UINT8_CLAMPED_ELEMENTS,
FIRST_FAST_ELEMENTS_KIND = FAST_SMI_ELEMENTS,
LAST_FAST_ELEMENTS_KIND = FAST_HOLEY_DOUBLE_ELEMENTS,
FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_BYTE_ELEMENTS,
LAST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS,
+ FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_ELEMENTS,
+ LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_CLAMPED_ELEMENTS,
TERMINAL_FAST_ELEMENTS_KIND = FAST_HOLEY_ELEMENTS
};
@@ -103,6 +116,12 @@
}
+inline bool IsFixedTypedArrayElementsKind(ElementsKind kind) {
+ return kind >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
+ kind <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
+}
+
+
inline bool IsFastElementsKind(ElementsKind kind) {
ASSERT(FIRST_FAST_ELEMENTS_KIND == 0);
return kind <= FAST_HOLEY_DOUBLE_ELEMENTS;
@@ -121,9 +140,15 @@
}
+inline bool IsFixedFloatElementsKind(ElementsKind kind) {
+ return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS;
+}
+
+
inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
return IsFastDoubleElementsKind(kind) ||
- IsExternalFloatOrDoubleElementsKind(kind);
+ IsExternalFloatOrDoubleElementsKind(kind) ||
+ IsFixedFloatElementsKind(kind);
}
diff --git a/src/elements.cc b/src/elements.cc
index 0b745c4..5bce3b9 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -48,7 +48,7 @@
// - FastDoubleElementsAccessor
// - FastPackedDoubleElementsAccessor
// - FastHoleyDoubleElementsAccessor
-// - ExternalElementsAccessor (abstract)
+// - TypedElementsAccessor (abstract)
// - ExternalByteElementsAccessor
// - ExternalUnsignedByteElementsAccessor
// - ExternalShortElementsAccessor
@@ -58,6 +58,15 @@
// - ExternalFloatElementsAccessor
// - ExternalDoubleElementsAccessor
// - PixelElementsAccessor
+// - FixedUint8ArrayAccessor
+// - FixedInt8ArrayAccessor
+// - FixedUint16ArrayAccessor
+// - FixedInt16ArrayAccessor
+// - FixedUint32ArrayAccessor
+// - FixedInt32ArrayAccessor
+// - FixedFloat32ArrayAccessor
+// - FixedFloat64ArrayAccessor
+// - FixedUint8ClampedArrayAccessor
// - DictionaryElementsAccessor
// - NonStrictArgumentsElementsAccessor
@@ -104,7 +113,17 @@
EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray) \
V(ExternalDoubleElementsAccessor, \
EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray) \
- V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray)
+ V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray) \
+ V(FixedUint8ArrayAccessor, UINT8_ELEMENTS, FixedUint8Array) \
+ V(FixedInt8ArrayAccessor, INT8_ELEMENTS, FixedInt8Array) \
+ V(FixedUint16ArrayAccessor, UINT16_ELEMENTS, FixedUint16Array) \
+ V(FixedInt16ArrayAccessor, INT16_ELEMENTS, FixedInt16Array) \
+ V(FixedUint32ArrayAccessor, UINT32_ELEMENTS, FixedUint32Array) \
+ V(FixedInt32ArrayAccessor, INT32_ELEMENTS, FixedInt32Array) \
+ V(FixedFloat32ArrayAccessor, FLOAT32_ELEMENTS, FixedFloat32Array) \
+ V(FixedFloat64ArrayAccessor, FLOAT64_ELEMENTS, FixedFloat64Array) \
+ V(FixedUint8ClampedArrayAccessor, UINT8_CLAMPED_ELEMENTS, \
+ FixedUint8ClampedArray)
template<ElementsKind Kind> class ElementsKindTraits {
@@ -1096,6 +1115,26 @@
return EXTERNAL_DOUBLE_ELEMENTS;
case EXTERNAL_PIXEL_ARRAY_TYPE:
return EXTERNAL_PIXEL_ELEMENTS;
+
+ case FIXED_UINT8_ARRAY_TYPE:
+ return UINT8_ELEMENTS;
+ case FIXED_INT8_ARRAY_TYPE:
+ return INT8_ELEMENTS;
+ case FIXED_UINT16_ARRAY_TYPE:
+ return UINT16_ELEMENTS;
+ case FIXED_INT16_ARRAY_TYPE:
+ return INT16_ELEMENTS;
+ case FIXED_UINT32_ARRAY_TYPE:
+ return UINT32_ELEMENTS;
+ case FIXED_INT32_ARRAY_TYPE:
+ return INT32_ELEMENTS;
+ case FIXED_FLOAT32_ARRAY_TYPE:
+ return FLOAT32_ELEMENTS;
+ case FIXED_FLOAT64_ARRAY_TYPE:
+ return FLOAT64_ELEMENTS;
+ case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
+ return UINT8_CLAMPED_ELEMENTS;
+
default:
UNREACHABLE();
}
@@ -1158,6 +1197,15 @@
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
UNREACHABLE();
}
return NULL;
@@ -1283,6 +1331,15 @@
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
UNREACHABLE();
}
return to->GetHeap()->undefined_value();
@@ -1320,20 +1377,20 @@
// Super class for all external element arrays.
-template<typename ExternalElementsAccessorSubclass,
+template<typename AccessorSubclass,
ElementsKind Kind>
-class ExternalElementsAccessor
- : public ElementsAccessorBase<ExternalElementsAccessorSubclass,
+class TypedElementsAccessor
+ : public ElementsAccessorBase<AccessorSubclass,
ElementsKindTraits<Kind> > {
public:
- explicit ExternalElementsAccessor(const char* name)
- : ElementsAccessorBase<ExternalElementsAccessorSubclass,
+ explicit TypedElementsAccessor(const char* name)
+ : ElementsAccessorBase<AccessorSubclass,
ElementsKindTraits<Kind> >(name) {}
protected:
typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore;
- friend class ElementsAccessorBase<ExternalElementsAccessorSubclass,
+ friend class ElementsAccessorBase<AccessorSubclass,
ElementsKindTraits<Kind> >;
MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver,
@@ -1341,7 +1398,7 @@
uint32_t key,
FixedArrayBase* backing_store) {
return
- key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
+ key < AccessorSubclass::GetCapacityImpl(backing_store)
? BackingStore::cast(backing_store)->get(key)
: backing_store->GetHeap()->undefined_value();
}
@@ -1352,7 +1409,7 @@
uint32_t key,
FixedArrayBase* backing_store) {
return
- key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
+ key < AccessorSubclass::GetCapacityImpl(backing_store)
? NONE : ABSENT;
}
@@ -1362,7 +1419,7 @@
uint32_t key,
FixedArrayBase* backing_store) {
return
- key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
+ key < AccessorSubclass::GetCapacityImpl(backing_store)
? FIELD : NONEXISTENT;
}
@@ -1387,102 +1444,176 @@
uint32_t key,
FixedArrayBase* backing_store) {
uint32_t capacity =
- ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store);
+ AccessorSubclass::GetCapacityImpl(backing_store);
return key < capacity;
}
};
class ExternalByteElementsAccessor
- : public ExternalElementsAccessor<ExternalByteElementsAccessor,
- EXTERNAL_BYTE_ELEMENTS> {
+ : public TypedElementsAccessor<ExternalByteElementsAccessor,
+ EXTERNAL_BYTE_ELEMENTS> {
public:
explicit ExternalByteElementsAccessor(const char* name)
- : ExternalElementsAccessor<ExternalByteElementsAccessor,
- EXTERNAL_BYTE_ELEMENTS>(name) {}
+ : TypedElementsAccessor<ExternalByteElementsAccessor,
+ EXTERNAL_BYTE_ELEMENTS>(name) {}
};
class ExternalUnsignedByteElementsAccessor
- : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
- EXTERNAL_UNSIGNED_BYTE_ELEMENTS> {
+ : public TypedElementsAccessor<ExternalUnsignedByteElementsAccessor,
+ EXTERNAL_UNSIGNED_BYTE_ELEMENTS> {
public:
explicit ExternalUnsignedByteElementsAccessor(const char* name)
- : ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
- EXTERNAL_UNSIGNED_BYTE_ELEMENTS>(name) {}
+ : TypedElementsAccessor<ExternalUnsignedByteElementsAccessor,
+ EXTERNAL_UNSIGNED_BYTE_ELEMENTS>(name) {}
};
class ExternalShortElementsAccessor
- : public ExternalElementsAccessor<ExternalShortElementsAccessor,
- EXTERNAL_SHORT_ELEMENTS> {
+ : public TypedElementsAccessor<ExternalShortElementsAccessor,
+ EXTERNAL_SHORT_ELEMENTS> {
public:
explicit ExternalShortElementsAccessor(const char* name)
- : ExternalElementsAccessor<ExternalShortElementsAccessor,
- EXTERNAL_SHORT_ELEMENTS>(name) {}
+ : TypedElementsAccessor<ExternalShortElementsAccessor,
+ EXTERNAL_SHORT_ELEMENTS>(name) {}
};
class ExternalUnsignedShortElementsAccessor
- : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
- EXTERNAL_UNSIGNED_SHORT_ELEMENTS> {
+ : public TypedElementsAccessor<ExternalUnsignedShortElementsAccessor,
+ EXTERNAL_UNSIGNED_SHORT_ELEMENTS> {
public:
explicit ExternalUnsignedShortElementsAccessor(const char* name)
- : ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
- EXTERNAL_UNSIGNED_SHORT_ELEMENTS>(name) {}
+ : TypedElementsAccessor<ExternalUnsignedShortElementsAccessor,
+ EXTERNAL_UNSIGNED_SHORT_ELEMENTS>(name) {}
};
class ExternalIntElementsAccessor
- : public ExternalElementsAccessor<ExternalIntElementsAccessor,
- EXTERNAL_INT_ELEMENTS> {
+ : public TypedElementsAccessor<ExternalIntElementsAccessor,
+ EXTERNAL_INT_ELEMENTS> {
public:
explicit ExternalIntElementsAccessor(const char* name)
- : ExternalElementsAccessor<ExternalIntElementsAccessor,
- EXTERNAL_INT_ELEMENTS>(name) {}
+ : TypedElementsAccessor<ExternalIntElementsAccessor,
+ EXTERNAL_INT_ELEMENTS>(name) {}
};
class ExternalUnsignedIntElementsAccessor
- : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
- EXTERNAL_UNSIGNED_INT_ELEMENTS> {
+ : public TypedElementsAccessor<ExternalUnsignedIntElementsAccessor,
+ EXTERNAL_UNSIGNED_INT_ELEMENTS> {
public:
explicit ExternalUnsignedIntElementsAccessor(const char* name)
- : ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
+ : TypedElementsAccessor<ExternalUnsignedIntElementsAccessor,
EXTERNAL_UNSIGNED_INT_ELEMENTS>(name) {}
};
class ExternalFloatElementsAccessor
- : public ExternalElementsAccessor<ExternalFloatElementsAccessor,
- EXTERNAL_FLOAT_ELEMENTS> {
+ : public TypedElementsAccessor<ExternalFloatElementsAccessor,
+ EXTERNAL_FLOAT_ELEMENTS> {
public:
explicit ExternalFloatElementsAccessor(const char* name)
- : ExternalElementsAccessor<ExternalFloatElementsAccessor,
- EXTERNAL_FLOAT_ELEMENTS>(name) {}
+ : TypedElementsAccessor<ExternalFloatElementsAccessor,
+ EXTERNAL_FLOAT_ELEMENTS>(name) {}
};
class ExternalDoubleElementsAccessor
- : public ExternalElementsAccessor<ExternalDoubleElementsAccessor,
- EXTERNAL_DOUBLE_ELEMENTS> {
+ : public TypedElementsAccessor<ExternalDoubleElementsAccessor,
+ EXTERNAL_DOUBLE_ELEMENTS> {
public:
explicit ExternalDoubleElementsAccessor(const char* name)
- : ExternalElementsAccessor<ExternalDoubleElementsAccessor,
- EXTERNAL_DOUBLE_ELEMENTS>(name) {}
+ : TypedElementsAccessor<ExternalDoubleElementsAccessor,
+ EXTERNAL_DOUBLE_ELEMENTS>(name) {}
};
class PixelElementsAccessor
- : public ExternalElementsAccessor<PixelElementsAccessor,
- EXTERNAL_PIXEL_ELEMENTS> {
+ : public TypedElementsAccessor<PixelElementsAccessor,
+ EXTERNAL_PIXEL_ELEMENTS> {
public:
explicit PixelElementsAccessor(const char* name)
- : ExternalElementsAccessor<PixelElementsAccessor,
- EXTERNAL_PIXEL_ELEMENTS>(name) {}
+ : TypedElementsAccessor<PixelElementsAccessor,
+ EXTERNAL_PIXEL_ELEMENTS>(name) {}
};
+class FixedUint8ArrayAccessor
+ : public TypedElementsAccessor<FixedUint8ArrayAccessor,
+ UINT8_ELEMENTS> {
+ public:
+ explicit FixedUint8ArrayAccessor(const char* name)
+ : TypedElementsAccessor<FixedUint8ArrayAccessor,
+ UINT8_ELEMENTS>(name) {}
+};
+class FixedUint8ClampedArrayAccessor
+ : public TypedElementsAccessor<FixedUint8ClampedArrayAccessor,
+ UINT8_CLAMPED_ELEMENTS> {
+ public:
+ explicit FixedUint8ClampedArrayAccessor(const char* name)
+ : TypedElementsAccessor<FixedUint8ClampedArrayAccessor,
+ UINT8_CLAMPED_ELEMENTS>(name) {}
+};
+class FixedInt8ArrayAccessor
+ : public TypedElementsAccessor<FixedInt8ArrayAccessor,
+ INT8_ELEMENTS> {
+ public:
+ explicit FixedInt8ArrayAccessor(const char* name)
+ : TypedElementsAccessor<FixedInt8ArrayAccessor,
+ INT8_ELEMENTS>(name) {}
+};
+class FixedUint16ArrayAccessor
+ : public TypedElementsAccessor<FixedUint16ArrayAccessor,
+ UINT16_ELEMENTS> {
+ public:
+ explicit FixedUint16ArrayAccessor(const char* name)
+ : TypedElementsAccessor<FixedUint16ArrayAccessor,
+ UINT16_ELEMENTS>(name) {}
+};
+class FixedInt16ArrayAccessor
+ : public TypedElementsAccessor<FixedInt16ArrayAccessor,
+ INT16_ELEMENTS> {
+ public:
+ explicit FixedInt16ArrayAccessor(const char* name)
+ : TypedElementsAccessor<FixedInt16ArrayAccessor,
+ INT16_ELEMENTS>(name) {}
+};
+class FixedUint32ArrayAccessor
+ : public TypedElementsAccessor<FixedUint32ArrayAccessor,
+ UINT32_ELEMENTS> {
+ public:
+ explicit FixedUint32ArrayAccessor(const char* name)
+ : TypedElementsAccessor<FixedUint32ArrayAccessor,
+ UINT32_ELEMENTS>(name) {}
+};
+class FixedInt32ArrayAccessor
+ : public TypedElementsAccessor<FixedInt32ArrayAccessor,
+ INT32_ELEMENTS> {
+ public:
+ explicit FixedInt32ArrayAccessor(const char* name)
+ : TypedElementsAccessor<FixedInt32ArrayAccessor,
+ INT32_ELEMENTS>(name) {}
+};
+
+class FixedFloat32ArrayAccessor
+ : public TypedElementsAccessor<FixedFloat32ArrayAccessor,
+ FLOAT32_ELEMENTS> {
+ public:
+ explicit FixedFloat32ArrayAccessor(const char* name)
+ : TypedElementsAccessor<FixedFloat32ArrayAccessor,
+ FLOAT32_ELEMENTS>(name) {}
+};
+class FixedFloat64ArrayAccessor
+ : public TypedElementsAccessor<FixedFloat64ArrayAccessor,
+ FLOAT64_ELEMENTS> {
+ public:
+ explicit FixedFloat64ArrayAccessor(const char* name)
+ : TypedElementsAccessor<FixedFloat64ArrayAccessor,
+ FLOAT64_ELEMENTS>(name) {}
+};
+
class DictionaryElementsAccessor
: public ElementsAccessorBase<DictionaryElementsAccessor,
ElementsKindTraits<DICTIONARY_ELEMENTS> > {
diff --git a/src/execution.cc b/src/execution.cc
index a9f72b3..da2d880 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -502,6 +502,19 @@
}
+bool StackGuard::IsDeoptMarkedCode() {
+ ExecutionAccess access(isolate_);
+ return (thread_local_.interrupt_flags_ & DEOPT_MARKED_CODE) != 0;
+}
+
+
+void StackGuard::DeoptMarkedCode() {
+ ExecutionAccess access(isolate_);
+ thread_local_.interrupt_flags_ |= DEOPT_MARKED_CODE;
+ set_interrupt_limits(access);
+}
+
+
#ifdef ENABLE_DEBUGGER_SUPPORT
bool StackGuard::IsDebugBreak() {
ExecutionAccess access(isolate_);
@@ -1013,6 +1026,10 @@
stack_guard->Continue(FULL_DEOPT);
Deoptimizer::DeoptimizeAll(isolate);
}
+ if (stack_guard->IsDeoptMarkedCode()) {
+ stack_guard->Continue(DEOPT_MARKED_CODE);
+ Deoptimizer::DeoptimizeMarkedCode(isolate);
+ }
if (stack_guard->IsInstallCodeRequest()) {
ASSERT(isolate->concurrent_recompilation_enabled());
stack_guard->Continue(INSTALL_CODE);
diff --git a/src/execution.h b/src/execution.h
index 3e62d87..abf4f1d 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -44,7 +44,8 @@
GC_REQUEST = 1 << 5,
FULL_DEOPT = 1 << 6,
INSTALL_CODE = 1 << 7,
- API_INTERRUPT = 1 << 8
+ API_INTERRUPT = 1 << 8,
+ DEOPT_MARKED_CODE = 1 << 9
};
@@ -221,6 +222,8 @@
void RequestInstallCode();
bool IsFullDeopt();
void FullDeopt();
+ bool IsDeoptMarkedCode();
+ void DeoptMarkedCode();
void Continue(InterruptFlag after_what);
void RequestInterrupt(InterruptCallback callback, void* data);
diff --git a/src/factory.cc b/src/factory.cc
index 9f1f085..2b5cf8b 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -729,7 +729,7 @@
ExternalArrayType array_type,
void* external_pointer,
PretenureFlag pretenure) {
- ASSERT(0 <= length);
+ ASSERT(0 <= length && length <= Smi::kMaxValue);
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateExternalArray(length,
@@ -740,6 +740,20 @@
}
+Handle<FixedTypedArrayBase> Factory::NewFixedTypedArray(
+ int length,
+ ExternalArrayType array_type,
+ PretenureFlag pretenure) {
+ ASSERT(0 <= length && length <= Smi::kMaxValue);
+ CALL_HEAP_FUNCTION(
+ isolate(),
+ isolate()->heap()->AllocateFixedTypedArray(length,
+ array_type,
+ pretenure),
+ FixedTypedArrayBase);
+}
+
+
Handle<Cell> Factory::NewCell(Handle<Object> value) {
AllowDeferredHandleDereference convert_to_cell;
CALL_HEAP_FUNCTION(
diff --git a/src/factory.h b/src/factory.h
index 94e89f5..8753bd8 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -257,6 +257,11 @@
void* external_pointer,
PretenureFlag pretenure = NOT_TENURED);
+ Handle<FixedTypedArrayBase> NewFixedTypedArray(
+ int length,
+ ExternalArrayType array_type,
+ PretenureFlag pretenure = NOT_TENURED);
+
Handle<Cell> NewCell(Handle<Object> value);
Handle<PropertyCell> NewPropertyCellWithHole();
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index c96baee..1136daa 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -220,7 +220,7 @@
// TODO(hpayer): We will remove this flag as soon as we have pretenuring
// support for specific allocation sites.
DEFINE_bool(pretenuring_call_new, false, "pretenure call new")
-DEFINE_bool(allocation_site_pretenuring, false,
+DEFINE_bool(allocation_site_pretenuring, true,
"pretenure with allocation sites")
DEFINE_bool(trace_pretenuring, false,
"trace pretenuring decisions of HAllocate instructions")
@@ -398,9 +398,7 @@
// bootstrapper.cc
DEFINE_string(expose_natives_as, NULL, "expose natives in global object")
DEFINE_string(expose_debug_as, NULL, "expose debug in global object")
-#ifdef ADDRESS_SANITIZER
DEFINE_bool(expose_free_buffer, false, "expose freeBuffer extension")
-#endif
DEFINE_bool(expose_gc, false, "expose gc extension")
DEFINE_string(expose_gc_as, NULL,
"expose gc extension under the specified name")
diff --git a/src/heap-inl.h b/src/heap-inl.h
index fedf450..d878daa 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -31,6 +31,7 @@
#include <cmath>
#include "heap.h"
+#include "heap-profiler.h"
#include "isolate.h"
#include "list-inl.h"
#include "objects.h"
@@ -666,7 +667,7 @@
} \
if (__maybe_object__->IsRetryAfterGC()) { \
/* TODO(1181417): Fix this. */ \
- v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); \
+ v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true);\
} \
RETURN_EMPTY; \
} while (false)
@@ -678,7 +679,7 @@
FUNCTION_CALL, \
RETURN_VALUE, \
RETURN_EMPTY, \
- v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY", true))
+ v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY", true))
#define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE) \
CALL_AND_RETRY_OR_DIE(ISOLATE, \
diff --git a/src/heap.cc b/src/heap.cc
index 07ba97a..5e3d759 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -521,6 +521,7 @@
int i = 0;
Object* list_element = allocation_sites_list();
+ bool trigger_deoptimization = false;
while (use_scratchpad ?
i < allocation_sites_scratchpad_length :
list_element->IsAllocationSite()) {
@@ -530,12 +531,11 @@
if (site->memento_found_count() > 0) {
active_allocation_sites++;
}
- if (site->DigestPretenuringFeedback()) {
- if (site->GetPretenureMode() == TENURED) {
- tenure_decisions++;
- } else {
- dont_tenure_decisions++;
- }
+ if (site->DigestPretenuringFeedback()) trigger_deoptimization = true;
+ if (site->GetPretenureMode() == TENURED) {
+ tenure_decisions++;
+ } else {
+ dont_tenure_decisions++;
}
allocation_sites++;
if (use_scratchpad) {
@@ -544,6 +544,9 @@
list_element = site->weak_next();
}
}
+
+ if (trigger_deoptimization) isolate_->stack_guard()->DeoptMarkedCode();
+
allocation_sites_scratchpad_length = 0;
// TODO(mvstanton): Pretenure decisions are only made once for an allocation
@@ -1983,14 +1986,22 @@
void Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) {
+ ASSERT(AllowCodeDependencyChange::IsAllowed());
+ DisallowHeapAllocation no_allocation_scope;
Object* cur = allocation_sites_list();
+ bool marked = false;
while (cur->IsAllocationSite()) {
AllocationSite* casted = AllocationSite::cast(cur);
if (casted->GetPretenureMode() == flag) {
casted->ResetPretenureDecision();
+ bool got_marked = casted->dependent_code()->MarkCodeForDeoptimization(
+ isolate_,
+ DependentCode::kAllocationSiteTenuringChangedGroup);
+ if (got_marked) marked = true;
}
cur = casted->weak_next();
}
+ if (marked) isolate_->stack_guard()->DeoptMarkedCode();
}
@@ -2138,6 +2149,8 @@
table_.Register(kVisitByteArray, &EvacuateByteArray);
table_.Register(kVisitFixedArray, &EvacuateFixedArray);
table_.Register(kVisitFixedDoubleArray, &EvacuateFixedDoubleArray);
+ table_.Register(kVisitFixedTypedArray, &EvacuateFixedTypedArray);
+ table_.Register(kVisitFixedFloat64Array, &EvacuateFixedFloat64Array);
table_.Register(kVisitNativeContext,
&ObjectEvacuationStrategy<POINTER_OBJECT>::
@@ -2378,6 +2391,24 @@
}
+ static inline void EvacuateFixedTypedArray(Map* map,
+ HeapObject** slot,
+ HeapObject* object) {
+ int object_size = reinterpret_cast<FixedTypedArrayBase*>(object)->size();
+ EvacuateObject<DATA_OBJECT, kObjectAlignment>(
+ map, slot, object, object_size);
+ }
+
+
+ static inline void EvacuateFixedFloat64Array(Map* map,
+ HeapObject** slot,
+ HeapObject* object) {
+ int object_size = reinterpret_cast<FixedFloat64Array*>(object)->size();
+ EvacuateObject<DATA_OBJECT, kDoubleAlignment>(
+ map, slot, object, object_size);
+ }
+
+
static inline void EvacuateByteArray(Map* map,
HeapObject** slot,
HeapObject* object) {
@@ -2767,291 +2798,136 @@
constant_pool_array_map()->set_prototype(null_value());
constant_pool_array_map()->set_constructor(null_value());
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_fixed_cow_array_map(Map::cast(obj));
- ASSERT(fixed_array_map() != fixed_cow_array_map());
-
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_scope_info_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_heap_number_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(SYMBOL_TYPE, Symbol::kSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_symbol_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(FOREIGN_TYPE, Foreign::kSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_foreign_map(Map::cast(obj));
-
- for (unsigned i = 0; i < ARRAY_SIZE(string_type_table); i++) {
- const StringTypeTable& entry = string_type_table[i];
- { MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size);
- if (!maybe_obj->ToObject(&obj)) return false;
+ { // Map allocation
+#define ALLOCATE_MAP(instance_type, size, field_name) \
+ { Map* map; \
+ if (!AllocateMap((instance_type), size)->To(&map)) return false; \
+ set_##field_name##_map(map); \
}
- roots_[entry.index] = Map::cast(obj);
- }
- { MaybeObject* maybe_obj = AllocateMap(STRING_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_undetectable_string_map(Map::cast(obj));
- Map::cast(obj)->set_is_undetectable();
+#define ALLOCATE_VARSIZE_MAP(instance_type, field_name) \
+ ALLOCATE_MAP(instance_type, kVariableSizeSentinel, field_name)
- { MaybeObject* maybe_obj =
- AllocateMap(ASCII_STRING_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_undetectable_ascii_string_map(Map::cast(obj));
- Map::cast(obj)->set_is_undetectable();
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, fixed_cow_array)
+ ASSERT(fixed_array_map() != fixed_cow_array_map());
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_DOUBLE_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_fixed_double_array_map(Map::cast(obj));
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, scope_info)
+ ALLOCATE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number)
+ ALLOCATE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol)
+ ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign)
- { MaybeObject* maybe_obj =
- AllocateMap(BYTE_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_byte_array_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj =
- AllocateMap(FREE_SPACE_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_free_space_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateByteArray(0, TENURED);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_empty_byte_array(ByteArray::cast(obj));
-
- { MaybeObject* maybe_obj =
- AllocateMap(EXTERNAL_PIXEL_ARRAY_TYPE, ExternalArray::kAlignedSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_external_pixel_array_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE,
- ExternalArray::kAlignedSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_external_byte_array_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
- ExternalArray::kAlignedSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_external_unsigned_byte_array_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_SHORT_ARRAY_TYPE,
- ExternalArray::kAlignedSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_external_short_array_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
- ExternalArray::kAlignedSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_external_unsigned_short_array_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_INT_ARRAY_TYPE,
- ExternalArray::kAlignedSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_external_int_array_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
- ExternalArray::kAlignedSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_external_unsigned_int_array_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_FLOAT_ARRAY_TYPE,
- ExternalArray::kAlignedSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_external_float_array_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_non_strict_arguments_elements_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_DOUBLE_ARRAY_TYPE,
- ExternalArray::kAlignedSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_external_double_array_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalByteArray);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_empty_external_byte_array(ExternalArray::cast(obj));
-
- { MaybeObject* maybe_obj =
- AllocateEmptyExternalArray(kExternalUnsignedByteArray);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_empty_external_unsigned_byte_array(ExternalArray::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalShortArray);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_empty_external_short_array(ExternalArray::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateEmptyExternalArray(
- kExternalUnsignedShortArray);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_empty_external_unsigned_short_array(ExternalArray::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalIntArray);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_empty_external_int_array(ExternalArray::cast(obj));
-
- { MaybeObject* maybe_obj =
- AllocateEmptyExternalArray(kExternalUnsignedIntArray);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_empty_external_unsigned_int_array(ExternalArray::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalFloatArray);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_empty_external_float_array(ExternalArray::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalDoubleArray);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_empty_external_double_array(ExternalArray::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalPixelArray);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_empty_external_pixel_array(ExternalArray::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(CODE_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_code_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(CELL_TYPE, Cell::kSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_cell_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(PROPERTY_CELL_TYPE,
- PropertyCell::kSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_global_property_cell_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(FILLER_TYPE, kPointerSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_one_pointer_filler_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(FILLER_TYPE, 2 * kPointerSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_two_pointer_filler_map(Map::cast(obj));
-
- for (unsigned i = 0; i < ARRAY_SIZE(struct_table); i++) {
- const StructTable& entry = struct_table[i];
- { MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size);
- if (!maybe_obj->ToObject(&obj)) return false;
+ for (unsigned i = 0; i < ARRAY_SIZE(string_type_table); i++) {
+ const StringTypeTable& entry = string_type_table[i];
+ { MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size);
+ if (!maybe_obj->ToObject(&obj)) return false;
+ }
+ roots_[entry.index] = Map::cast(obj);
}
- roots_[entry.index] = Map::cast(obj);
+
+ ALLOCATE_VARSIZE_MAP(STRING_TYPE, undetectable_string)
+ undetectable_string_map()->set_is_undetectable();
+
+ ALLOCATE_VARSIZE_MAP(ASCII_STRING_TYPE, undetectable_ascii_string);
+ undetectable_ascii_string_map()->set_is_undetectable();
+
+ ALLOCATE_VARSIZE_MAP(FIXED_DOUBLE_ARRAY_TYPE, fixed_double_array)
+ ALLOCATE_VARSIZE_MAP(BYTE_ARRAY_TYPE, byte_array)
+ ALLOCATE_VARSIZE_MAP(FREE_SPACE_TYPE, free_space)
+
+#define ALLOCATE_EXTERNAL_ARRAY_MAP(TYPE, type) \
+ ALLOCATE_MAP(EXTERNAL_##TYPE##_ARRAY_TYPE, ExternalArray::kAlignedSize, \
+ external_##type##_array)
+
+ ALLOCATE_EXTERNAL_ARRAY_MAP(PIXEL, pixel)
+ ALLOCATE_EXTERNAL_ARRAY_MAP(BYTE, byte)
+ ALLOCATE_EXTERNAL_ARRAY_MAP(UNSIGNED_BYTE, unsigned_byte)
+ ALLOCATE_EXTERNAL_ARRAY_MAP(SHORT, short) // NOLINT
+ ALLOCATE_EXTERNAL_ARRAY_MAP(UNSIGNED_SHORT, unsigned_short)
+ ALLOCATE_EXTERNAL_ARRAY_MAP(INT, int)
+ ALLOCATE_EXTERNAL_ARRAY_MAP(UNSIGNED_INT, unsigned_int)
+ ALLOCATE_EXTERNAL_ARRAY_MAP(FLOAT, float)
+ ALLOCATE_EXTERNAL_ARRAY_MAP(DOUBLE, double)
+#undef ALLOCATE_EXTERNAL_ARRAY_MAP
+
+ ALLOCATE_VARSIZE_MAP(FIXED_UINT8_ARRAY_TYPE, fixed_uint8_array)
+ ALLOCATE_VARSIZE_MAP(FIXED_UINT8_CLAMPED_ARRAY_TYPE,
+ fixed_uint8_clamped_array)
+ ALLOCATE_VARSIZE_MAP(FIXED_INT8_ARRAY_TYPE, fixed_int8_array)
+ ALLOCATE_VARSIZE_MAP(FIXED_UINT16_ARRAY_TYPE, fixed_uint16_array)
+ ALLOCATE_VARSIZE_MAP(FIXED_INT16_ARRAY_TYPE, fixed_int16_array)
+ ALLOCATE_VARSIZE_MAP(FIXED_UINT32_ARRAY_TYPE, fixed_uint32_array)
+ ALLOCATE_VARSIZE_MAP(FIXED_INT32_ARRAY_TYPE, fixed_int32_array)
+ ALLOCATE_VARSIZE_MAP(FIXED_FLOAT32_ARRAY_TYPE, fixed_float32_array)
+ ALLOCATE_VARSIZE_MAP(FIXED_FLOAT64_ARRAY_TYPE, fixed_float64_array)
+
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, non_strict_arguments_elements)
+
+ ALLOCATE_VARSIZE_MAP(CODE_TYPE, code)
+
+ ALLOCATE_MAP(CELL_TYPE, Cell::kSize, cell)
+ ALLOCATE_MAP(PROPERTY_CELL_TYPE, PropertyCell::kSize, global_property_cell)
+ ALLOCATE_MAP(FILLER_TYPE, kPointerSize, one_pointer_filler)
+ ALLOCATE_MAP(FILLER_TYPE, 2 * kPointerSize, two_pointer_filler)
+
+
+ for (unsigned i = 0; i < ARRAY_SIZE(struct_table); i++) {
+ const StructTable& entry = struct_table[i];
+ Map* map;
+ if (!AllocateMap(entry.type, entry.size)->To(&map))
+ return false;
+ roots_[entry.index] = map;
+ }
+
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, hash_table)
+
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, function_context)
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, catch_context)
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, with_context)
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, block_context)
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, module_context)
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, global_context)
+
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, native_context)
+ native_context_map()->set_dictionary_map(true);
+ native_context_map()->set_visitor_id(
+ StaticVisitorBase::kVisitNativeContext);
+
+ ALLOCATE_MAP(SHARED_FUNCTION_INFO_TYPE, SharedFunctionInfo::kAlignedSize,
+ shared_function_info)
+
+ ALLOCATE_MAP(JS_MESSAGE_OBJECT_TYPE, JSMessageObject::kSize,
+ message_object)
+ ALLOCATE_MAP(JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize,
+ external)
+ external_map()->set_is_extensible(false);
+#undef ALLOCATE_VARSIZE_MAP
+#undef ALLOCATE_MAP
}
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_hash_table_map(Map::cast(obj));
+ { // Empty arrays
+ { ByteArray* byte_array;
+ if (!AllocateByteArray(0, TENURED)->To(&byte_array)) return false;
+ set_empty_byte_array(byte_array);
+ }
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_function_context_map(Map::cast(obj));
+#define ALLOCATE_EMPTY_EXTERNAL_ARRAY(Type, type) \
+ { ExternalArray* obj; \
+ if (!AllocateEmptyExternalArray(kExternal##Type##Array)->To(&obj)) \
+ return false; \
+ set_empty_external_##type##_array(obj); \
+ }
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
+ ALLOCATE_EMPTY_EXTERNAL_ARRAY(Byte, byte)
+ ALLOCATE_EMPTY_EXTERNAL_ARRAY(UnsignedByte, unsigned_byte)
+ ALLOCATE_EMPTY_EXTERNAL_ARRAY(Short, short) // NOLINT
+ ALLOCATE_EMPTY_EXTERNAL_ARRAY(UnsignedShort, unsigned_short)
+ ALLOCATE_EMPTY_EXTERNAL_ARRAY(Int, int)
+ ALLOCATE_EMPTY_EXTERNAL_ARRAY(UnsignedInt, unsigned_int)
+ ALLOCATE_EMPTY_EXTERNAL_ARRAY(Float, float)
+ ALLOCATE_EMPTY_EXTERNAL_ARRAY(Double, double)
+ ALLOCATE_EMPTY_EXTERNAL_ARRAY(Pixel, pixel)
+#undef ALLOCATE_EMPTY_EXTERNAL_ARRAY
}
- set_catch_context_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_with_context_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_block_context_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_module_context_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_global_context_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj =
- AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- Map* native_context_map = Map::cast(obj);
- native_context_map->set_dictionary_map(true);
- native_context_map->set_visitor_id(StaticVisitorBase::kVisitNativeContext);
- set_native_context_map(native_context_map);
-
- { MaybeObject* maybe_obj = AllocateMap(SHARED_FUNCTION_INFO_TYPE,
- SharedFunctionInfo::kAlignedSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_shared_function_info_map(Map::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateMap(JS_MESSAGE_OBJECT_TYPE,
- JSMessageObject::kSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_message_object_map(Map::cast(obj));
-
- Map* external_map;
- { MaybeObject* maybe_obj =
- AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize);
- if (!maybe_obj->To(&external_map)) return false;
- }
- external_map->set_is_extensible(false);
- set_external_map(external_map);
-
ASSERT(!InNewSpace(empty_fixed_array()));
return true;
}
@@ -3760,6 +3636,39 @@
}
+Map* Heap::MapForFixedTypedArray(ExternalArrayType array_type) {
+ return Map::cast(roots_[RootIndexForFixedTypedArray(array_type)]);
+}
+
+
+Heap::RootListIndex Heap::RootIndexForFixedTypedArray(
+ ExternalArrayType array_type) {
+ switch (array_type) {
+ case kExternalByteArray:
+ return kFixedInt8ArrayMapRootIndex;
+ case kExternalUnsignedByteArray:
+ return kFixedUint8ArrayMapRootIndex;
+ case kExternalShortArray:
+ return kFixedInt16ArrayMapRootIndex;
+ case kExternalUnsignedShortArray:
+ return kFixedUint16ArrayMapRootIndex;
+ case kExternalIntArray:
+ return kFixedInt32ArrayMapRootIndex;
+ case kExternalUnsignedIntArray:
+ return kFixedUint32ArrayMapRootIndex;
+ case kExternalFloatArray:
+ return kFixedFloat32ArrayMapRootIndex;
+ case kExternalDoubleArray:
+ return kFixedFloat64ArrayMapRootIndex;
+ case kExternalPixelArray:
+ return kFixedUint8ClampedArrayMapRootIndex;
+ default:
+ UNREACHABLE();
+ return kUndefinedValueRootIndex;
+ }
+}
+
+
Heap::RootListIndex Heap::RootIndexForEmptyExternalArray(
ElementsKind elementsKind) {
switch (elementsKind) {
@@ -4018,6 +3927,84 @@
return result;
}
+static void ForFixedTypedArray(ExternalArrayType array_type,
+ int* element_size,
+ ElementsKind* element_kind) {
+ switch (array_type) {
+ case kExternalUnsignedByteArray:
+ *element_size = 1;
+ *element_kind = UINT8_ELEMENTS;
+ return;
+ case kExternalByteArray:
+ *element_size = 1;
+ *element_kind = INT8_ELEMENTS;
+ return;
+ case kExternalUnsignedShortArray:
+ *element_size = 2;
+ *element_kind = UINT16_ELEMENTS;
+ return;
+ case kExternalShortArray:
+ *element_size = 2;
+ *element_kind = INT16_ELEMENTS;
+ return;
+ case kExternalUnsignedIntArray:
+ *element_size = 4;
+ *element_kind = UINT32_ELEMENTS;
+ return;
+ case kExternalIntArray:
+ *element_size = 4;
+ *element_kind = INT32_ELEMENTS;
+ return;
+ case kExternalFloatArray:
+ *element_size = 4;
+ *element_kind = FLOAT32_ELEMENTS;
+ return;
+ case kExternalDoubleArray:
+ *element_size = 8;
+ *element_kind = FLOAT64_ELEMENTS;
+ return;
+ case kExternalPixelArray:
+ *element_size = 1;
+ *element_kind = UINT8_CLAMPED_ELEMENTS;
+ return;
+ default:
+ *element_size = 0; // Bogus
+ *element_kind = UINT8_ELEMENTS; // Bogus
+ UNREACHABLE();
+ }
+}
+
+
+MaybeObject* Heap::AllocateFixedTypedArray(int length,
+ ExternalArrayType array_type,
+ PretenureFlag pretenure) {
+ int element_size;
+ ElementsKind elements_kind;
+ ForFixedTypedArray(array_type, &element_size, &elements_kind);
+ int size = OBJECT_POINTER_ALIGN(
+ length * element_size + FixedTypedArrayBase::kDataOffset);
+#ifndef V8_HOST_ARCH_64_BIT
+ if (array_type == kExternalDoubleArray) {
+ size += kPointerSize;
+ }
+#endif
+ AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
+
+ HeapObject* object;
+ MaybeObject* maybe_object = AllocateRaw(size, space, OLD_DATA_SPACE);
+ if (!maybe_object->To(&object)) return maybe_object;
+
+ if (array_type == kExternalDoubleArray) {
+ object = EnsureDoubleAligned(this, object, size);
+ }
+
+ FixedTypedArrayBase* elements =
+ reinterpret_cast<FixedTypedArrayBase*>(object);
+ elements->set_map(MapForFixedTypedArray(array_type));
+ elements->set_length(length);
+ return elements;
+}
+
MaybeObject* Heap::CreateCode(const CodeDesc& desc,
Code::Flags flags,
@@ -6811,6 +6798,10 @@
}
+void Heap::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
+ v8::internal::V8::FatalProcessOutOfMemory(location, take_snapshot);
+}
+
#ifdef DEBUG
class PrintHandleVisitor: public ObjectVisitor {
diff --git a/src/heap.h b/src/heap.h
index fec6f54..0847298 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -156,6 +156,15 @@
V(ExternalArray, empty_external_double_array, EmptyExternalDoubleArray) \
V(ExternalArray, empty_external_pixel_array, \
EmptyExternalPixelArray) \
+ V(Map, fixed_uint8_array_map, FixedUint8ArrayMap) \
+ V(Map, fixed_int8_array_map, FixedInt8ArrayMap) \
+ V(Map, fixed_uint16_array_map, FixedUint16ArrayMap) \
+ V(Map, fixed_int16_array_map, FixedInt16ArrayMap) \
+ V(Map, fixed_uint32_array_map, FixedUint32ArrayMap) \
+ V(Map, fixed_int32_array_map, FixedInt32ArrayMap) \
+ V(Map, fixed_float32_array_map, FixedFloat32ArrayMap) \
+ V(Map, fixed_float64_array_map, FixedFloat64ArrayMap) \
+ V(Map, fixed_uint8_clamped_array_map, FixedUint8ClampedArrayMap) \
V(Map, non_strict_arguments_elements_map, NonStrictArgumentsElementsMap) \
V(Map, function_context_map, FunctionContextMap) \
V(Map, catch_context_map, CatchContextMap) \
@@ -875,6 +884,15 @@
void* external_pointer,
PretenureFlag pretenure);
+ // Allocates a fixed typed array of the specified length and type.
+ // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+ // failed.
+ // Please note this does not perform a garbage collection.
+ MUST_USE_RESULT MaybeObject* AllocateFixedTypedArray(
+ int length,
+ ExternalArrayType array_type,
+ PretenureFlag pretenure);
+
// Allocate a symbol in old space.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
@@ -1561,6 +1579,10 @@
MUST_USE_RESULT MaybeObject* Uint32ToString(
uint32_t value, bool check_number_string_cache = true);
+ Map* MapForFixedTypedArray(ExternalArrayType array_type);
+ RootListIndex RootIndexForFixedTypedArray(
+ ExternalArrayType array_type);
+
Map* MapForExternalArrayType(ExternalArrayType array_type);
RootListIndex RootIndexForExternalArrayType(
ExternalArrayType array_type);
@@ -1843,6 +1865,9 @@
void EnsureWeakObjectToCodeTable();
+ static void FatalProcessOutOfMemory(const char* location,
+ bool take_snapshot = false);
+
private:
Heap();
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index a19c3ee..beb339b 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -207,7 +207,8 @@
V(InobjectFields) \
V(OsrEntries) \
V(ExternalMemory) \
- V(StringChars)
+ V(StringChars) \
+ V(TypedArrayElements)
#define DECLARE_ABSTRACT_INSTRUCTION(type) \
@@ -6366,6 +6367,12 @@
bool is_external() const {
return IsExternalArrayElementsKind(elements_kind());
}
+ bool is_fixed_typed_array() const {
+ return IsFixedTypedArrayElementsKind(elements_kind());
+ }
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
HValue* elements() { return OperandAt(0); }
HValue* key() { return OperandAt(1); }
HValue* dependency() {
@@ -6394,9 +6401,10 @@
}
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- // kind_fast: tagged[int32] (none)
- // kind_double: tagged[int32] (none)
- // kind_external: external[int32] (none)
+ // kind_fast: tagged[int32] (none)
+ // kind_double: tagged[int32] (none)
+ // kind_fixed_typed_array: tagged[int32] (none)
+ // kind_external: external[int32] (none)
if (index == 0) {
return is_external() ? Representation::External()
: Representation::Tagged();
@@ -6446,7 +6454,7 @@
SetOperandAt(1, key);
SetOperandAt(2, dependency != NULL ? dependency : obj);
- if (!is_external()) {
+ if (!is_typed_elements()) {
// I can detect the case between storing double (holey and fast) and
// smi/object by looking at elements_kind_.
ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
@@ -6473,13 +6481,21 @@
}
} else {
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
- elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+ elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS ||
+ elements_kind == FLOAT64_ELEMENTS) {
set_representation(Representation::Double());
} else {
set_representation(Representation::Integer32());
}
- SetGVNFlag(kDependsOnExternalMemory);
+ if (is_external()) {
+ SetGVNFlag(kDependsOnExternalMemory);
+ } else if (is_fixed_typed_array()) {
+ SetGVNFlag(kDependsOnTypedArrayElements);
+ } else {
+ UNREACHABLE();
+ }
// Native code could change the specialized array.
SetGVNFlag(kDependsOnCalls);
}
@@ -6738,10 +6754,11 @@
ElementsKind, StoreFieldOrKeyedMode);
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- // kind_fast: tagged[int32] = tagged
- // kind_double: tagged[int32] = double
- // kind_smi : tagged[int32] = smi
- // kind_external: external[int32] = (double | int32)
+ // kind_fast: tagged[int32] = tagged
+ // kind_double: tagged[int32] = double
+ // kind_smi : tagged[int32] = smi
+ // kind_fixed_typed_array: tagged[int32] = (double | int32)
+ // kind_external: external[int32] = (double | int32)
if (index == 0) {
return is_external() ? Representation::External()
: Representation::Tagged();
@@ -6761,14 +6778,23 @@
return Representation::Smi();
}
- return is_external() ? Representation::Integer32()
- : Representation::Tagged();
+ return is_external() || is_fixed_typed_array()
+ ? Representation::Integer32()
+ : Representation::Tagged();
}
bool is_external() const {
return IsExternalArrayElementsKind(elements_kind());
}
+ bool is_fixed_typed_array() const {
+ return IsFixedTypedArrayElementsKind(elements_kind());
+ }
+
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
+
virtual Representation observed_input_representation(int index) V8_OVERRIDE {
if (index < 2) return RequiredInputRepresentation(index);
if (IsUninitialized()) {
@@ -6783,7 +6809,7 @@
if (IsFastSmiElementsKind(elements_kind())) {
return Representation::Smi();
}
- if (is_external()) {
+ if (is_typed_elements()) {
return Representation::Integer32();
}
// For fast object elements kinds, don't assume anything.
@@ -6868,13 +6894,18 @@
SetGVNFlag(kChangesDoubleArrayElements);
} else if (IsFastSmiElementsKind(elements_kind)) {
SetGVNFlag(kChangesArrayElements);
+ } else if (is_fixed_typed_array()) {
+ SetGVNFlag(kChangesTypedArrayElements);
+ SetFlag(kAllowUndefinedAsNaN);
} else {
SetGVNFlag(kChangesArrayElements);
}
// EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
- if (elements_kind >= EXTERNAL_BYTE_ELEMENTS &&
- elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) {
+ if ((elements_kind >= EXTERNAL_BYTE_ELEMENTS &&
+ elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) ||
+ (elements_kind >= UINT8_ELEMENTS &&
+ elements_kind <= INT32_ELEMENTS)) {
SetFlag(kTruncatingToInt32);
}
}
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 4185408..1d068a4 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -2078,7 +2078,9 @@
bool is_store,
LoadKeyedHoleMode load_mode,
KeyedAccessStoreMode store_mode) {
- ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
+ ASSERT((!IsExternalArrayElementsKind(elements_kind) &&
+ !IsFixedTypedArrayElementsKind(elements_kind)) ||
+ !is_js_array);
// No GVNFlag is necessary for ElementsKind if there is an explicit dependency
// on a HElementsTransition instruction. The flag can also be removed if the
// map to check has FAST_HOLEY_ELEMENTS, since there can be no further
@@ -2108,11 +2110,17 @@
}
length->set_type(HType::Smi());
HValue* checked_key = NULL;
- if (IsExternalArrayElementsKind(elements_kind)) {
+ if (IsExternalArrayElementsKind(elements_kind) ||
+ IsFixedTypedArrayElementsKind(elements_kind)) {
+ HValue* backing_store;
+ if (IsExternalArrayElementsKind(elements_kind)) {
+ backing_store =
+ Add<HLoadExternalArrayPointer>(elements);
+ } else {
+ backing_store = elements;
+ }
if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
NoObservableSideEffectsScope no_effects(this);
- HLoadExternalArrayPointer* external_elements =
- Add<HLoadExternalArrayPointer>(elements);
IfBuilder length_checker(this);
length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
length_checker.Then();
@@ -2121,7 +2129,7 @@
key, graph()->GetConstant0(), Token::GTE);
negative_checker.Then();
HInstruction* result = AddElementAccess(
- external_elements, key, val, bounds_check, elements_kind, is_store);
+ backing_store, key, val, bounds_check, elements_kind, is_store);
negative_checker.ElseDeopt("Negative key encountered");
negative_checker.End();
length_checker.End();
@@ -2129,10 +2137,8 @@
} else {
ASSERT(store_mode == STANDARD_STORE);
checked_key = Add<HBoundsCheck>(key, length);
- HLoadExternalArrayPointer* external_elements =
- Add<HLoadExternalArrayPointer>(elements);
return AddElementAccess(
- external_elements, checked_key, val,
+ backing_store, checked_key, val,
checked_object, elements_kind, is_store);
}
}
@@ -2313,7 +2319,8 @@
LoadKeyedHoleMode load_mode) {
if (is_store) {
ASSERT(val != NULL);
- if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
+ if (elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
+ elements_kind == UINT8_CLAMPED_ELEMENTS) {
val = Add<HClampToUint8>(val);
}
return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
@@ -2327,7 +2334,8 @@
HLoadKeyed* load = Add<HLoadKeyed>(
elements, checked_key, dependency, elements_kind, load_mode);
if (FLAG_opt_safe_uint32_operations &&
- elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
+ (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS ||
+ elements_kind == UINT32_ELEMENTS)) {
graph()->RecordUint32Instruction(load);
}
return load;
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 0a67231..93f3656 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -3421,7 +3421,8 @@
elements_kind,
0,
instr->additional_index()));
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS) {
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
XMMRegister result(ToDoubleRegister(instr->result()));
@@ -3430,7 +3431,8 @@
} else {
X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
}
- } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+ } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
+ elements_kind == FLOAT64_ELEMENTS) {
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
__ movsd(ToDoubleRegister(instr->result()), operand);
@@ -3441,22 +3443,29 @@
Register result(ToRegister(instr->result()));
switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
+ case INT8_ELEMENTS:
__ movsx_b(result, operand);
break;
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
__ movzx_b(result, operand);
break;
case EXTERNAL_SHORT_ELEMENTS:
+ case INT16_ELEMENTS:
__ movsx_w(result, operand);
break;
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case UINT16_ELEMENTS:
__ movzx_w(result, operand);
break;
case EXTERNAL_INT_ELEMENTS:
+ case INT32_ELEMENTS:
__ mov(result, operand);
break;
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case UINT32_ELEMENTS:
__ mov(result, operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ test(result, Operand(result));
@@ -3465,6 +3474,8 @@
break;
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@@ -3537,7 +3548,7 @@
void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
- if (instr->is_external()) {
+ if (instr->is_typed_elements()) {
DoLoadKeyedExternalArray(instr);
} else if (instr->hydrogen()->representation().IsDouble()) {
DoLoadKeyedFixedDoubleArray(instr);
@@ -3556,6 +3567,9 @@
uint32_t additional_index) {
Register elements_pointer_reg = ToRegister(elements_pointer);
int element_shift_size = ElementsKindToShiftSize(elements_kind);
+ if (IsFixedTypedArrayElementsKind(elements_kind)) {
+ offset += FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
+ }
int shift_size = element_shift_size;
if (key->IsConstantOperand()) {
int constant_value = ToInteger32(LConstantOperand::cast(key));
@@ -4538,7 +4552,8 @@
elements_kind,
0,
instr->additional_index()));
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS) {
if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
XMMRegister xmm_scratch = double_scratch0();
@@ -4548,7 +4563,8 @@
__ fld(0);
__ fstp_s(operand);
}
- } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+ } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
+ elements_kind == FLOAT64_ELEMENTS) {
if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
__ movsd(operand, ToDoubleRegister(instr->value()));
@@ -4561,18 +4577,27 @@
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
__ mov_b(operand, value);
break;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
__ mov_w(operand, value);
break;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
__ mov(operand, value);
break;
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@@ -4710,7 +4735,7 @@
void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
// By cases...external, fast-double, fast
- if (instr->is_external()) {
+ if (instr->is_typed_elements()) {
DoStoreKeyedExternalArray(instr);
} else if (instr->hydrogen()->value()->representation().IsDouble()) {
DoStoreKeyedFixedDoubleArray(instr);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 2e8ca36..3f3516d 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -2153,19 +2153,17 @@
: UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
- if (!instr->is_external()) {
+ if (!instr->is_typed_elements()) {
LOperand* obj = UseRegisterAtStart(instr->elements());
result = new(zone()) LLoadKeyed(obj, key);
} else {
ASSERT(
(instr->representation().IsInteger32() &&
- (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
- (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+ !(IsDoubleOrFloatElementsKind(instr->elements_kind()))) ||
(instr->representation().IsDouble() &&
- ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
- (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
- LOperand* external_pointer = UseRegister(instr->elements());
- result = new(zone()) LLoadKeyed(external_pointer, key);
+ (IsDoubleOrFloatElementsKind(instr->elements_kind()))));
+ LOperand* backing_store = UseRegister(instr->elements());
+ result = new(zone()) LLoadKeyed(backing_store, key);
}
DefineAsRegister(result);
@@ -2195,7 +2193,10 @@
bool val_is_fixed_register =
elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
- elements_kind == EXTERNAL_PIXEL_ELEMENTS;
+ elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
+ elements_kind == UINT8_ELEMENTS ||
+ elements_kind == INT8_ELEMENTS ||
+ elements_kind == UINT8_CLAMPED_ELEMENTS;
if (val_is_fixed_register) {
return UseFixed(instr->value(), eax);
}
@@ -2210,7 +2211,7 @@
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
- if (!instr->is_external()) {
+ if (!instr->is_typed_elements()) {
ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsSmi());
@@ -2242,23 +2243,22 @@
ElementsKind elements_kind = instr->elements_kind();
ASSERT(
(instr->value()->representation().IsInteger32() &&
- (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
- (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+ !IsDoubleOrFloatElementsKind(elements_kind)) ||
(instr->value()->representation().IsDouble() &&
- ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
- (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
- ASSERT(instr->elements()->representation().IsExternal());
+ IsDoubleOrFloatElementsKind(elements_kind)));
+ ASSERT((instr->is_fixed_typed_array() &&
+ instr->elements()->representation().IsTagged()) ||
+ (instr->is_external() &&
+ instr->elements()->representation().IsExternal()));
- LOperand* external_pointer = UseRegister(instr->elements());
+ LOperand* backing_store = UseRegister(instr->elements());
LOperand* val = GetStoreKeyedValueOperand(instr);
bool clobbers_key = ExternalArrayOpRequiresTemp(
instr->key()->representation(), elements_kind);
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
- return new(zone()) LStoreKeyed(external_pointer,
- key,
- val);
+ return new(zone()) LStoreKeyed(backing_store, key, val);
}
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index c6f95ad..680d5c8 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -1581,6 +1581,12 @@
bool is_external() const {
return hydrogen()->is_external();
}
+ bool is_fixed_typed_array() const {
+ return hydrogen()->is_fixed_typed_array();
+ }
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@@ -1602,7 +1608,10 @@
return key_representation.IsSmi() &&
(elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
- elements_kind == EXTERNAL_PIXEL_ELEMENTS);
+ elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
+ elements_kind == UINT8_ELEMENTS ||
+ elements_kind == INT8_ELEMENTS ||
+ elements_kind == UINT8_CLAMPED_ELEMENTS);
}
@@ -2232,6 +2241,12 @@
}
bool is_external() const { return hydrogen()->is_external(); }
+ bool is_fixed_typed_array() const {
+ return hydrogen()->is_fixed_typed_array();
+ }
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
diff --git a/src/ic.cc b/src/ic.cc
index 807bde0..07be39a 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -1845,7 +1845,8 @@
if (store_mode != STANDARD_STORE) {
int external_arrays = 0;
for (int i = 0; i < target_receiver_maps.length(); ++i) {
- if (target_receiver_maps[i]->has_external_array_elements()) {
+ if (target_receiver_maps[i]->has_external_array_elements() ||
+ target_receiver_maps[i]->has_fixed_typed_array_elements()) {
external_arrays++;
}
}
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 0fb0cca..9a08123 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -692,7 +692,6 @@
RelocInfo::Mode mode,
LInstruction* instr,
SafepointMode safepoint_mode) {
- EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
ASSERT(instr != NULL);
__ Call(code, mode);
RecordSafepointWithLazyDeopt(instr, safepoint_mode);
@@ -3083,10 +3082,16 @@
int element_size_shift = ElementsKindToShiftSize(elements_kind);
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
- int additional_offset = instr->additional_index() << element_size_shift;
+ int additional_offset = IsFixedTypedArrayElementsKind(elements_kind)
+ ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
+ : 0;
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
- elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+ elements_kind == FLOAT32_ELEMENTS ||
+ elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
+ elements_kind == FLOAT64_ELEMENTS) {
+ int base_offset =
+ (instr->additional_index() << element_size_shift) + additional_offset;
FPURegister result = ToDoubleRegister(instr->result());
if (key_is_constant) {
__ Addu(scratch0(), external_pointer, constant_key << element_size_shift);
@@ -3094,11 +3099,12 @@
__ sll(scratch0(), key, shift_size);
__ Addu(scratch0(), scratch0(), external_pointer);
}
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
- __ lwc1(result, MemOperand(scratch0(), additional_offset));
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS) {
+ __ lwc1(result, MemOperand(scratch0(), base_offset));
__ cvt_d_s(result, result);
- } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
- __ ldc1(result, MemOperand(scratch0(), additional_offset));
+ } else { // loading doubles, not floats.
+ __ ldc1(result, MemOperand(scratch0(), base_offset));
}
} else {
Register result = ToRegister(instr->result());
@@ -3108,28 +3114,37 @@
instr->additional_index(), additional_offset);
switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
+ case INT8_ELEMENTS:
__ lb(result, mem_operand);
break;
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
__ lbu(result, mem_operand);
break;
case EXTERNAL_SHORT_ELEMENTS:
+ case INT16_ELEMENTS:
__ lh(result, mem_operand);
break;
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case UINT16_ELEMENTS:
__ lhu(result, mem_operand);
break;
case EXTERNAL_INT_ELEMENTS:
+ case INT32_ELEMENTS:
__ lw(result, mem_operand);
break;
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case UINT32_ELEMENTS:
__ lw(result, mem_operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
DeoptimizeIf(Ugreater_equal, instr->environment(),
result, Operand(0x80000000));
}
break;
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@@ -3228,7 +3243,7 @@
void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
- if (instr->is_external()) {
+ if (instr->is_typed_elements()) {
DoLoadKeyedExternalArray(instr);
} else if (instr->hydrogen()->representation().IsDouble()) {
DoLoadKeyedFixedDoubleArray(instr);
@@ -3246,14 +3261,28 @@
int shift_size,
int additional_index,
int additional_offset) {
- if (additional_index != 0 && !key_is_constant) {
- additional_index *= 1 << (element_size - shift_size);
- __ Addu(scratch0(), key, Operand(additional_index));
- }
-
+ int base_offset = (additional_index << element_size) + additional_offset;
if (key_is_constant) {
return MemOperand(base,
- (constant_key << element_size) + additional_offset);
+ base_offset + (constant_key << element_size));
+ }
+
+ if (additional_offset != 0) {
+ if (shift_size >= 0) {
+ __ sll(scratch0(), key, shift_size);
+ __ Addu(scratch0(), scratch0(), Operand(base_offset));
+ } else {
+ ASSERT_EQ(-1, shift_size);
+ __ srl(scratch0(), key, 1);
+ __ Addu(scratch0(), scratch0(), Operand(base_offset));
+ }
+ __ Addu(scratch0(), base, scratch0());
+ return MemOperand(scratch0());
+ }
+
+ if (additional_index != 0) {
+ additional_index *= 1 << (element_size - shift_size);
+ __ Addu(scratch0(), key, Operand(additional_index));
}
if (additional_index == 0) {
@@ -4179,10 +4208,16 @@
int element_size_shift = ElementsKindToShiftSize(elements_kind);
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
- int additional_offset = instr->additional_index() << element_size_shift;
+ int additional_offset = IsFixedTypedArrayElementsKind(elements_kind)
+ ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
+ : 0;
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
- elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+ elements_kind == FLOAT32_ELEMENTS ||
+ elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
+ elements_kind == FLOAT64_ELEMENTS) {
+ int base_offset =
+ (instr->additional_index() << element_size_shift) + additional_offset;
Register address = scratch0();
FPURegister value(ToDoubleRegister(instr->value()));
if (key_is_constant) {
@@ -4197,11 +4232,12 @@
__ Addu(address, external_pointer, address);
}
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS) {
__ cvt_s_d(double_scratch0(), value);
- __ swc1(double_scratch0(), MemOperand(address, additional_offset));
- } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
- __ sdc1(value, MemOperand(address, additional_offset));
+ __ swc1(double_scratch0(), MemOperand(address, base_offset));
+ } else { // Storing doubles, not floats.
+ __ sdc1(value, MemOperand(address, base_offset));
}
} else {
Register value(ToRegister(instr->value()));
@@ -4213,16 +4249,25 @@
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
+ case INT8_ELEMENTS:
__ sb(value, mem_operand);
break;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT16_ELEMENTS:
__ sh(value, mem_operand);
break;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case INT32_ELEMENTS:
+ case UINT32_ELEMENTS:
__ sw(value, mem_operand);
break;
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@@ -4341,7 +4386,7 @@
void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
// By cases: external, fast double
- if (instr->is_external()) {
+ if (instr->is_typed_elements()) {
DoStoreKeyedExternalArray(instr);
} else if (instr->hydrogen()->value()->representation().IsDouble()) {
DoStoreKeyedFixedDoubleArray(instr);
@@ -5575,24 +5620,25 @@
void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
- if (info()->IsStub()) return;
- // Ensure that we have enough space after the previous lazy-bailout
- // instruction for patching the code here.
- int current_pc = masm()->pc_offset();
- if (current_pc < last_lazy_deopt_pc_ + space_needed) {
- int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
- ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
- while (padding_size > 0) {
- __ nop();
- padding_size -= Assembler::kInstrSize;
+ if (!info()->IsStub()) {
+ // Ensure that we have enough space after the previous lazy-bailout
+ // instruction for patching the code here.
+ int current_pc = masm()->pc_offset();
+ if (current_pc < last_lazy_deopt_pc_ + space_needed) {
+ int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
+ ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
+ while (padding_size > 0) {
+ __ nop();
+ padding_size -= Assembler::kInstrSize;
+ }
}
}
+ last_lazy_deopt_pc_ = masm()->pc_offset();
}
void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
- last_lazy_deopt_pc_ = masm()->pc_offset();
ASSERT(instr->HasEnvironment());
LEnvironment* env = instr->environment();
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
@@ -5665,7 +5711,6 @@
RelocInfo::CODE_TARGET,
instr);
EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
- last_lazy_deopt_pc_ = masm()->pc_offset();
__ bind(&done);
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
@@ -5677,7 +5722,6 @@
__ LoadRoot(at, Heap::kStackLimitRootIndex);
__ Branch(deferred_stack_check->entry(), lo, sp, Operand(at));
EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
- last_lazy_deopt_pc_ = masm()->pc_offset();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 1298b4c..2676d43 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -2035,7 +2035,7 @@
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
- if (!instr->is_external()) {
+ if (!instr->is_typed_elements()) {
LOperand* obj = NULL;
if (instr->representation().IsDouble()) {
obj = UseRegister(instr->elements());
@@ -2047,20 +2047,19 @@
} else {
ASSERT(
(instr->representation().IsInteger32() &&
- (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
- (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+ !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->representation().IsDouble() &&
- ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
- (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
- LOperand* external_pointer = UseRegister(instr->elements());
- result = new(zone()) LLoadKeyed(external_pointer, key);
+ IsDoubleOrFloatElementsKind(instr->elements_kind())));
+ LOperand* backing_store = UseRegister(instr->elements());
+ result = new(zone()) LLoadKeyed(backing_store, key);
}
DefineAsRegister(result);
// An unsigned int array load might overflow and cause a deopt, make sure it
// has an environment.
bool can_deoptimize = instr->RequiresHoleCheck() ||
- (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
+ elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS ||
+ elements_kind == UINT32_ELEMENTS;
return can_deoptimize ? AssignEnvironment(result) : result;
}
@@ -2077,7 +2076,7 @@
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
- if (!instr->is_external()) {
+ if (!instr->is_typed_elements()) {
ASSERT(instr->elements()->representation().IsTagged());
bool needs_write_barrier = instr->NeedsWriteBarrier();
LOperand* object = NULL;
@@ -2106,17 +2105,17 @@
ASSERT(
(instr->value()->representation().IsInteger32() &&
- (instr->elements_kind() != EXTERNAL_FLOAT_ELEMENTS) &&
- (instr->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS)) ||
+ !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->value()->representation().IsDouble() &&
- ((instr->elements_kind() == EXTERNAL_FLOAT_ELEMENTS) ||
- (instr->elements_kind() == EXTERNAL_DOUBLE_ELEMENTS))));
- ASSERT(instr->elements()->representation().IsExternal());
+ IsDoubleOrFloatElementsKind(instr->elements_kind())));
+ ASSERT((instr->is_fixed_typed_array() &&
+ instr->elements()->representation().IsTagged()) ||
+ (instr->is_external() &&
+ instr->elements()->representation().IsExternal()));
LOperand* val = UseRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
- LOperand* external_pointer = UseRegister(instr->elements());
-
- return new(zone()) LStoreKeyed(external_pointer, key, val);
+ LOperand* backing_store = UseRegister(instr->elements());
+ return new(zone()) LStoreKeyed(backing_store, key, val);
}
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index 009b116..4bda5f7 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -1575,6 +1575,12 @@
bool is_external() const {
return hydrogen()->is_external();
}
+ bool is_fixed_typed_array() const {
+ return hydrogen()->is_fixed_typed_array();
+ }
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@@ -2207,6 +2213,12 @@
}
bool is_external() const { return hydrogen()->is_external(); }
+ bool is_fixed_typed_array() const {
+ return hydrogen()->is_fixed_typed_array();
+ }
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index ed93e1d..414f2bc 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -132,6 +132,33 @@
case EXTERNAL_DOUBLE_ARRAY_TYPE:
ExternalDoubleArray::cast(this)->ExternalDoubleArrayVerify();
break;
+ case FIXED_UINT8_ARRAY_TYPE:
+ FixedUint8Array::cast(this)->FixedTypedArrayVerify();
+ break;
+ case FIXED_INT8_ARRAY_TYPE:
+ FixedInt8Array::cast(this)->FixedTypedArrayVerify();
+ break;
+ case FIXED_UINT16_ARRAY_TYPE:
+ FixedUint16Array::cast(this)->FixedTypedArrayVerify();
+ break;
+ case FIXED_INT16_ARRAY_TYPE:
+ FixedInt16Array::cast(this)->FixedTypedArrayVerify();
+ break;
+ case FIXED_UINT32_ARRAY_TYPE:
+ FixedUint32Array::cast(this)->FixedTypedArrayVerify();
+ break;
+ case FIXED_INT32_ARRAY_TYPE:
+ FixedInt32Array::cast(this)->FixedTypedArrayVerify();
+ break;
+ case FIXED_FLOAT32_ARRAY_TYPE:
+ FixedFloat32Array::cast(this)->FixedTypedArrayVerify();
+ break;
+ case FIXED_FLOAT64_ARRAY_TYPE:
+ FixedFloat64Array::cast(this)->FixedTypedArrayVerify();
+ break;
+ case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
+ FixedUint8ClampedArray::cast(this)->FixedTypedArrayVerify();
+ break;
case CODE_TYPE:
Code::cast(this)->CodeVerify();
break;
@@ -307,6 +334,14 @@
}
+template <class Traits>
+void FixedTypedArray<Traits>::FixedTypedArrayVerify() {
+ CHECK(IsHeapObject() &&
+ HeapObject::cast(this)->map()->instance_type() ==
+ Traits::kInstanceType);
+}
+
+
bool JSObject::ElementsAreSafeToExamine() {
return (FLAG_use_gvn && FLAG_use_allocation_folding) ||
reinterpret_cast<Map*>(elements()) !=
@@ -1087,9 +1122,18 @@
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
- case EXTERNAL_PIXEL_ELEMENTS: {
+ case EXTERNAL_PIXEL_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS: {
info->number_of_objects_with_fast_elements_++;
- ExternalPixelArray* e = ExternalPixelArray::cast(elements());
+ FixedArrayBase* e = FixedArrayBase::cast(elements());
info->number_of_fast_used_elements_ += e->length();
break;
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 49e4d69..7bd8d59 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -41,6 +41,7 @@
#include "conversions-inl.h"
#include "heap.h"
#include "isolate.h"
+#include "heap-inl.h"
#include "property.h"
#include "spaces.h"
#include "store-buffer.h"
@@ -86,6 +87,13 @@
}
+#define FIXED_TYPED_ARRAY_CAST_ACCESSOR(type) \
+ template<> \
+ type* type::cast(Object* object) { \
+ SLOW_ASSERT(object->Is##type()); \
+ return reinterpret_cast<type*>(object); \
+ }
+
#define INT_ACCESSORS(holder, name, offset) \
int holder::name() { return READ_INT_FIELD(this, offset); } \
void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
@@ -134,7 +142,8 @@
bool Object::IsFixedArrayBase() {
- return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray();
+ return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray() ||
+ IsFixedTypedArrayBase() || IsExternalArray();
}
@@ -262,7 +271,8 @@
bool Object::HasValidElements() {
// Dictionary is covered under FixedArray.
- return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray();
+ return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray() ||
+ IsFixedTypedArrayBase();
}
@@ -488,6 +498,27 @@
TYPE_CHECKER(ExternalDoubleArray, EXTERNAL_DOUBLE_ARRAY_TYPE)
+bool Object::IsFixedTypedArrayBase() {
+ if (!Object::IsHeapObject()) return false;
+
+ InstanceType instance_type =
+ HeapObject::cast(this)->map()->instance_type();
+ return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
+ instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE);
+}
+
+
+TYPE_CHECKER(FixedUint8Array, FIXED_UINT8_ARRAY_TYPE)
+TYPE_CHECKER(FixedInt8Array, FIXED_INT8_ARRAY_TYPE)
+TYPE_CHECKER(FixedUint16Array, FIXED_UINT16_ARRAY_TYPE)
+TYPE_CHECKER(FixedInt16Array, FIXED_INT16_ARRAY_TYPE)
+TYPE_CHECKER(FixedUint32Array, FIXED_UINT32_ARRAY_TYPE)
+TYPE_CHECKER(FixedInt32Array, FIXED_INT32_ARRAY_TYPE)
+TYPE_CHECKER(FixedFloat32Array, FIXED_FLOAT32_ARRAY_TYPE)
+TYPE_CHECKER(FixedFloat64Array, FIXED_FLOAT64_ARRAY_TYPE)
+TYPE_CHECKER(FixedUint8ClampedArray, FIXED_UINT8_CLAMPED_ARRAY_TYPE)
+
+
bool MaybeObject::IsFailure() {
return HAS_FAILURE_TAG(this);
}
@@ -1397,7 +1428,7 @@
inline bool AllocationSite::DigestPretenuringFeedback() {
- bool decision_made = false;
+ bool decision_changed = false;
int create_count = memento_create_count();
if (create_count >= kPretenureMinimumCreated) {
int found_count = memento_found_count();
@@ -1411,9 +1442,9 @@
? kTenure
: kDontTenure;
set_pretenure_decision(result);
- decision_made = true;
if (current_mode != GetPretenureMode()) {
- dependent_code()->DeoptimizeDependentCodeGroup(
+ decision_changed = true;
+ dependent_code()->MarkCodeForDeoptimization(
GetIsolate(),
DependentCode::kAllocationSiteTenuringChangedGroup);
}
@@ -1422,7 +1453,7 @@
// Clear feedback calculation fields until the next gc.
set_memento_found_count(0);
set_memento_create_count(0);
- return decision_made;
+ return decision_changed;
}
@@ -1955,8 +1986,7 @@
FixedArrayBase* FixedArrayBase::cast(Object* object) {
- ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray() ||
- object->IsConstantPoolArray());
+ ASSERT(object->IsFixedArrayBase());
return reinterpret_cast<FixedArrayBase*>(object);
}
@@ -2635,6 +2665,7 @@
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedDoubleArray)
+CAST_ACCESSOR(FixedTypedArrayBase)
CAST_ACCESSOR(ConstantPoolArray)
CAST_ACCESSOR(DescriptorArray)
CAST_ACCESSOR(DeoptimizationInputData)
@@ -2704,6 +2735,14 @@
CAST_ACCESSOR(Struct)
CAST_ACCESSOR(AccessorInfo)
+template <class Traits>
+FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) {
+ SLOW_ASSERT(object->IsHeapObject() &&
+ HeapObject::cast(object)->map()->instance_type() ==
+ Traits::kInstanceType);
+ return reinterpret_cast<FixedTypedArray<Traits>*>(object);
+}
+
#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
STRUCT_LIST(MAKE_STRUCT_CAST)
@@ -3479,6 +3518,133 @@
}
+int FixedTypedArrayBase::size() {
+ InstanceType instance_type = map()->instance_type();
+ int element_size;
+ switch (instance_type) {
+ case FIXED_UINT8_ARRAY_TYPE:
+ case FIXED_INT8_ARRAY_TYPE:
+ case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
+ element_size = 1;
+ break;
+ case FIXED_UINT16_ARRAY_TYPE:
+ case FIXED_INT16_ARRAY_TYPE:
+ element_size = 2;
+ break;
+ case FIXED_UINT32_ARRAY_TYPE:
+ case FIXED_INT32_ARRAY_TYPE:
+ case FIXED_FLOAT32_ARRAY_TYPE:
+ element_size = 4;
+ break;
+ case FIXED_FLOAT64_ARRAY_TYPE:
+ element_size = 8;
+ break;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+ return OBJECT_POINTER_ALIGN(kDataOffset + length() * element_size);
+}
+
+
+template <class Traits>
+typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
+ ASSERT((index >= 0) && (index < this->length()));
+ ElementType* ptr = reinterpret_cast<ElementType*>(
+ FIELD_ADDR(this, kDataOffset));
+ return ptr[index];
+}
+
+template <class Traits>
+void FixedTypedArray<Traits>::set(int index, ElementType value) {
+ ASSERT((index >= 0) && (index < this->length()));
+ ElementType* ptr = reinterpret_cast<ElementType*>(
+ FIELD_ADDR(this, kDataOffset));
+ ptr[index] = value;
+}
+
+
+template <class Traits>
+MaybeObject* FixedTypedArray<Traits>::get(int index) {
+ return Traits::ToObject(GetHeap(), get_scalar(index));
+}
+
+template <class Traits>
+MaybeObject* FixedTypedArray<Traits>::SetValue(uint32_t index, Object* value) {
+ ElementType cast_value = Traits::defaultValue();
+ if (index < static_cast<uint32_t>(length())) {
+ if (value->IsSmi()) {
+ int int_value = Smi::cast(value)->value();
+ cast_value = static_cast<ElementType>(int_value);
+ } else if (value->IsHeapNumber()) {
+ double double_value = HeapNumber::cast(value)->value();
+ cast_value = static_cast<ElementType>(DoubleToInt32(double_value));
+ } else {
+ // Clamp undefined to the default value. All other types have been
+ // converted to a number type further up in the call chain.
+ ASSERT(value->IsUndefined());
+ }
+ set(index, cast_value);
+ }
+ return Traits::ToObject(GetHeap(), cast_value);
+}
+
+template <class Traits>
+Handle<Object> FixedTypedArray<Traits>::SetValue(
+ Handle<FixedTypedArray<Traits> > array,
+ uint32_t index,
+ Handle<Object> value) {
+ CALL_HEAP_FUNCTION(array->GetIsolate(),
+ array->SetValue(index, *value),
+ Object);
+}
+
+
+MaybeObject* Uint8ArrayTraits::ToObject(Heap*, uint8_t scalar) {
+ return Smi::FromInt(scalar);
+}
+
+
+MaybeObject* Uint8ClampedArrayTraits::ToObject(Heap*, uint8_t scalar) {
+ return Smi::FromInt(scalar);
+}
+
+
+MaybeObject* Int8ArrayTraits::ToObject(Heap*, int8_t scalar) {
+ return Smi::FromInt(scalar);
+}
+
+
+MaybeObject* Uint16ArrayTraits::ToObject(Heap*, uint16_t scalar) {
+ return Smi::FromInt(scalar);
+}
+
+
+MaybeObject* Int16ArrayTraits::ToObject(Heap*, int16_t scalar) {
+ return Smi::FromInt(scalar);
+}
+
+
+MaybeObject* Uint32ArrayTraits::ToObject(Heap* heap, uint32_t scalar) {
+ return heap->NumberFromUint32(scalar);
+}
+
+
+MaybeObject* Int32ArrayTraits::ToObject(Heap* heap, int32_t scalar) {
+ return heap->NumberFromInt32(scalar);
+}
+
+
+MaybeObject* Float32ArrayTraits::ToObject(Heap* heap, float scalar) {
+ return heap->NumberFromDouble(scalar);
+}
+
+
+MaybeObject* Float64ArrayTraits::ToObject(Heap* heap, double scalar) {
+ return heap->NumberFromDouble(scalar);
+}
+
+
int Map::visitor_id() {
return READ_BYTE_FIELD(this, kVisitorIdOffset);
}
@@ -3539,6 +3705,10 @@
reinterpret_cast<ConstantPoolArray*>(this)->count_of_ptr_entries(),
reinterpret_cast<ConstantPoolArray*>(this)->count_of_int32_entries());
}
+ if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
+ instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
+ return reinterpret_cast<FixedTypedArrayBase*>(this)->size();
+ }
ASSERT(instance_type == CODE_TYPE);
return reinterpret_cast<Code*>(this)->CodeSize();
}
@@ -5707,6 +5877,13 @@
EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
+bool JSObject::HasFixedTypedArrayElements() {
+ HeapObject* array = elements();
+ ASSERT(array != NULL);
+ return array->IsFixedTypedArrayBase();
+}
+
+
bool JSObject::HasNamedInterceptor() {
return map()->has_named_interceptor();
}
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 219b692..ef98d57 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -136,6 +136,24 @@
case EXTERNAL_DOUBLE_ARRAY_TYPE:
ExternalDoubleArray::cast(this)->ExternalDoubleArrayPrint(out);
break;
+#define PRINT_FIXED_TYPED_ARRAY(Type) \
+ case Fixed##Type##Array::kInstanceType: \
+ Fixed##Type##Array::cast(this)->FixedTypedArrayPrint(out); \
+ break;
+
+ PRINT_FIXED_TYPED_ARRAY(Uint8)
+ PRINT_FIXED_TYPED_ARRAY(Int8)
+ PRINT_FIXED_TYPED_ARRAY(Uint16)
+ PRINT_FIXED_TYPED_ARRAY(Int16)
+ PRINT_FIXED_TYPED_ARRAY(Uint32)
+ PRINT_FIXED_TYPED_ARRAY(Int32)
+ PRINT_FIXED_TYPED_ARRAY(Float32)
+ PRINT_FIXED_TYPED_ARRAY(Float64)
+ PRINT_FIXED_TYPED_ARRAY(Uint8Clamped)
+
+#undef PPINT_FIXED_TYPED_ARRAY
+
+
case FILLER_TYPE:
PrintF(out, "filler");
break;
@@ -285,6 +303,11 @@
PrintF(out, "external double array");
}
+template <class Traits>
+void FixedTypedArray<Traits>::FixedTypedArrayPrint(FILE* out) {
+ PrintF(out, "fixed %s", Traits::Designator());
+}
+
void JSObject::PrintProperties(FILE* out) {
if (HasFastProperties()) {
@@ -324,6 +347,24 @@
}
+template<class T>
+static void DoPrintElements(FILE *out, Object* object) {
+ T* p = T::cast(object);
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: %d\n", i, p->get_scalar(i));
+ }
+}
+
+
+template<class T>
+static void DoPrintDoubleElements(FILE* out, Object* object) {
+ T* p = T::cast(object);
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: %f\n", i, p->get_scalar(i));
+ }
+}
+
+
void JSObject::PrintElements(FILE* out) {
// Don't call GetElementsKind, its validation code can cause the printer to
// fail when debugging.
@@ -357,72 +398,47 @@
}
break;
}
- case EXTERNAL_PIXEL_ELEMENTS: {
- ExternalPixelArray* p = ExternalPixelArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, p->get_scalar(i));
- }
- break;
+
+
+#define PRINT_ELEMENTS(Kind, Type) \
+ case Kind: { \
+ DoPrintElements<Type>(out, elements()); \
+ break; \
}
- case EXTERNAL_BYTE_ELEMENTS: {
- ExternalByteArray* p = ExternalByteArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
- }
- break;
+
+#define PRINT_DOUBLE_ELEMENTS(Kind, Type) \
+ case Kind: { \
+ DoPrintDoubleElements<Type>(out, elements()); \
+ break; \
}
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
- ExternalUnsignedByteArray* p =
- ExternalUnsignedByteArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
- }
- break;
- }
- case EXTERNAL_SHORT_ELEMENTS: {
- ExternalShortArray* p = ExternalShortArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
- }
- break;
- }
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
- ExternalUnsignedShortArray* p =
- ExternalUnsignedShortArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
- }
- break;
- }
- case EXTERNAL_INT_ELEMENTS: {
- ExternalIntArray* p = ExternalIntArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
- }
- break;
- }
- case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
- ExternalUnsignedIntArray* p =
- ExternalUnsignedIntArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
- }
- break;
- }
- case EXTERNAL_FLOAT_ELEMENTS: {
- ExternalFloatArray* p = ExternalFloatArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %f\n", i, p->get_scalar(i));
- }
- break;
- }
- case EXTERNAL_DOUBLE_ELEMENTS: {
- ExternalDoubleArray* p = ExternalDoubleArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %f\n", i, p->get_scalar(i));
- }
- break;
- }
+
+ PRINT_ELEMENTS(EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray)
+ PRINT_ELEMENTS(EXTERNAL_BYTE_ELEMENTS, ExternalByteArray)
+ PRINT_ELEMENTS(EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
+ ExternalUnsignedByteArray)
+ PRINT_ELEMENTS(EXTERNAL_SHORT_ELEMENTS, ExternalShortArray)
+ PRINT_ELEMENTS(EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
+ ExternalUnsignedShortArray)
+ PRINT_ELEMENTS(EXTERNAL_INT_ELEMENTS, ExternalIntArray)
+ PRINT_ELEMENTS(EXTERNAL_UNSIGNED_INT_ELEMENTS,
+ ExternalUnsignedIntArray)
+ PRINT_DOUBLE_ELEMENTS(EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray)
+ PRINT_DOUBLE_ELEMENTS(EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray)
+
+
+ PRINT_ELEMENTS(UINT8_ELEMENTS, FixedUint8Array)
+ PRINT_ELEMENTS(UINT8_CLAMPED_ELEMENTS, FixedUint8ClampedArray)
+ PRINT_ELEMENTS(INT8_ELEMENTS, FixedInt8Array)
+ PRINT_ELEMENTS(UINT16_ELEMENTS, FixedUint16Array)
+ PRINT_ELEMENTS(INT16_ELEMENTS, FixedInt16Array)
+ PRINT_ELEMENTS(UINT32_ELEMENTS, FixedUint32Array)
+ PRINT_ELEMENTS(INT32_ELEMENTS, FixedInt32Array)
+ PRINT_DOUBLE_ELEMENTS(FLOAT32_ELEMENTS, FixedFloat32Array)
+ PRINT_DOUBLE_ELEMENTS(FLOAT64_ELEMENTS, FixedFloat64Array)
+
+#undef PRINT_DOUBLE_ELEMENTS
+#undef PRINT_ELEMENTS
+
case DICTIONARY_ELEMENTS:
elements()->Print(out);
break;
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index b951342..5201a7b 100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -60,6 +60,8 @@
int>::Visit);
table_.Register(kVisitFixedDoubleArray, &VisitFixedDoubleArray);
+ table_.Register(kVisitFixedTypedArray, &VisitFixedTypedArray);
+ table_.Register(kVisitFixedFloat64Array, &VisitFixedTypedArray);
table_.Register(kVisitNativeContext,
&FixedBodyVisitor<StaticVisitor,
@@ -185,6 +187,10 @@
table_.Register(kVisitFixedDoubleArray, &DataObjectVisitor::Visit);
+ table_.Register(kVisitFixedTypedArray, &DataObjectVisitor::Visit);
+
+ table_.Register(kVisitFixedFloat64Array, &DataObjectVisitor::Visit);
+
table_.Register(kVisitConstantPoolArray, &VisitConstantPoolArray);
table_.Register(kVisitNativeContext, &VisitNativeContext);
diff --git a/src/objects-visiting.cc b/src/objects-visiting.cc
index 5ced2cf..e268768 100644
--- a/src/objects-visiting.cc
+++ b/src/objects-visiting.cc
@@ -184,6 +184,19 @@
kVisitDataObjectGeneric,
instance_size);
+ case FIXED_UINT8_ARRAY_TYPE:
+ case FIXED_INT8_ARRAY_TYPE:
+ case FIXED_UINT16_ARRAY_TYPE:
+ case FIXED_INT16_ARRAY_TYPE:
+ case FIXED_UINT32_ARRAY_TYPE:
+ case FIXED_INT32_ARRAY_TYPE:
+ case FIXED_FLOAT32_ARRAY_TYPE:
+ case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
+ return kVisitFixedTypedArray;
+
+ case FIXED_FLOAT64_ARRAY_TYPE:
+ return kVisitFixedFloat64Array;
+
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE:
STRUCT_LIST(MAKE_STRUCT_CASE)
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index f7758fd..cb76365 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -47,13 +47,15 @@
class StaticVisitorBase : public AllStatic {
public:
#define VISITOR_ID_LIST(V) \
- V(SeqOneByteString) \
+ V(SeqOneByteString) \
V(SeqTwoByteString) \
V(ShortcutCandidate) \
V(ByteArray) \
V(FreeSpace) \
V(FixedArray) \
V(FixedDoubleArray) \
+ V(FixedTypedArray) \
+ V(FixedFloat64Array) \
V(ConstantPoolArray) \
V(NativeContext) \
V(AllocationSite) \
@@ -322,6 +324,10 @@
return FixedDoubleArray::SizeFor(length);
}
+ INLINE(static int VisitFixedTypedArray(Map* map, HeapObject* object)) {
+ return reinterpret_cast<FixedTypedArrayBase*>(object)->size();
+ }
+
INLINE(static int VisitJSObject(Map* map, HeapObject* object)) {
return JSObjectVisitor::Visit(map, object);
}
diff --git a/src/objects.cc b/src/objects.cc
index 6899caa..18a811b 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1677,6 +1677,10 @@
accumulator->Add("<ExternalDoubleArray[%u]>",
ExternalDoubleArray::cast(this)->length());
break;
+ case FIXED_UINT8_ARRAY_TYPE:
+ accumulator->Add("<FixedUint8Array[%u]>",
+ FixedUint8Array::cast(this)->length());
+ break;
case SHARED_FUNCTION_INFO_TYPE: {
SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
SmartArrayPointer<char> debug_name =
@@ -1866,6 +1870,15 @@
case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
case EXTERNAL_FLOAT_ARRAY_TYPE:
case EXTERNAL_DOUBLE_ARRAY_TYPE:
+ case FIXED_INT8_ARRAY_TYPE:
+ case FIXED_UINT8_ARRAY_TYPE:
+ case FIXED_INT16_ARRAY_TYPE:
+ case FIXED_UINT16_ARRAY_TYPE:
+ case FIXED_INT32_ARRAY_TYPE:
+ case FIXED_UINT32_ARRAY_TYPE:
+ case FIXED_FLOAT32_ARRAY_TYPE:
+ case FIXED_FLOAT64_ARRAY_TYPE:
+ case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
break;
case SHARED_FUNCTION_INFO_TYPE: {
SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
@@ -5377,6 +5390,15 @@
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
// Raw pixels and external arrays do not reference other
// objects.
break;
@@ -5869,6 +5891,15 @@
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
// No contained objects, nothing to do.
break;
}
@@ -6106,6 +6137,15 @@
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
// Ignore getters and setters on pixel and external array elements.
return;
case DICTIONARY_ELEMENTS:
@@ -6564,6 +6604,15 @@
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
// Ignore getters and setters on pixel and external array
// elements.
return factory->undefined_value();
@@ -11755,7 +11804,7 @@
}
-void DependentCode::DeoptimizeDependentCodeGroup(
+bool DependentCode::MarkCodeForDeoptimization(
Isolate* isolate,
DependentCode::DependencyGroup group) {
ASSERT(AllowCodeDependencyChange::IsAllowed());
@@ -11764,7 +11813,7 @@
int start = starts.at(group);
int end = starts.at(group + 1);
int code_entries = starts.number_of_entries();
- if (start == end) return;
+ if (start == end) return false;
// Mark all the code that needs to be deoptimized.
bool marked = false;
@@ -11790,6 +11839,16 @@
clear_at(i);
}
set_number_of_entries(group, 0);
+ return marked;
+}
+
+
+void DependentCode::DeoptimizeDependentCodeGroup(
+ Isolate* isolate,
+ DependentCode::DependencyGroup group) {
+ ASSERT(AllowCodeDependencyChange::IsAllowed());
+ DisallowHeapAllocation no_allocation_scope;
+ bool marked = MarkCodeForDeoptimization(isolate, group);
if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
}
@@ -12711,6 +12770,51 @@
ExternalDoubleArray::cast(object->elements()));
return ExternalDoubleArray::SetValue(array, index, value);
}
+ case UINT8_ELEMENTS: {
+ Handle<FixedUint8Array> array(
+ FixedUint8Array::cast(object->elements()));
+ return FixedUint8Array::SetValue(array, index, value);
+ }
+ case UINT8_CLAMPED_ELEMENTS: {
+ Handle<FixedUint8ClampedArray> array(
+ FixedUint8ClampedArray::cast(object->elements()));
+ return FixedUint8ClampedArray::SetValue(array, index, value);
+ }
+ case INT8_ELEMENTS: {
+ Handle<FixedInt8Array> array(
+ FixedInt8Array::cast(object->elements()));
+ return FixedInt8Array::SetValue(array, index, value);
+ }
+ case UINT16_ELEMENTS: {
+ Handle<FixedUint16Array> array(
+ FixedUint16Array::cast(object->elements()));
+ return FixedUint16Array::SetValue(array, index, value);
+ }
+ case INT16_ELEMENTS: {
+ Handle<FixedInt16Array> array(
+ FixedInt16Array::cast(object->elements()));
+ return FixedInt16Array::SetValue(array, index, value);
+ }
+ case UINT32_ELEMENTS: {
+ Handle<FixedUint32Array> array(
+ FixedUint32Array::cast(object->elements()));
+ return FixedUint32Array::SetValue(array, index, value);
+ }
+ case INT32_ELEMENTS: {
+ Handle<FixedInt32Array> array(
+ FixedInt32Array::cast(object->elements()));
+ return FixedInt32Array::SetValue(array, index, value);
+ }
+ case FLOAT32_ELEMENTS: {
+ Handle<FixedFloat32Array> array(
+ FixedFloat32Array::cast(object->elements()));
+ return FixedFloat32Array::SetValue(array, index, value);
+ }
+ case FLOAT64_ELEMENTS: {
+ Handle<FixedFloat64Array> array(
+ FixedFloat64Array::cast(object->elements()));
+ return FixedFloat64Array::SetValue(array, index, value);
+ }
case DICTIONARY_ELEMENTS:
return SetDictionaryElement(object, index, value, attributes, strict_mode,
check_prototype,
@@ -12765,9 +12869,6 @@
void AllocationSite::ResetPretenureDecision() {
- dependent_code()->DeoptimizeDependentCodeGroup(
- GetIsolate(),
- DependentCode::kAllocationSiteTenuringChangedGroup);
set_pretenure_decision(kUndecided);
set_memento_found_count(0);
set_memento_create_count(0);
@@ -13125,11 +13226,21 @@
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS: {
// External arrays are considered 100% used.
- ExternalArray* external_array = ExternalArray::cast(elements());
+ FixedArrayBase* external_array = FixedArrayBase::cast(elements());
*capacity = external_array->length();
*used = external_array->length();
break;
+ }
}
}
@@ -13637,8 +13748,17 @@
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
- case EXTERNAL_DOUBLE_ELEMENTS: {
- int length = ExternalArray::cast(elements())->length();
+ case EXTERNAL_DOUBLE_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS: {
+ int length = FixedArrayBase::cast(elements())->length();
while (counter < length) {
if (storage != NULL) {
storage->set(counter, Smi::FromInt(counter));
diff --git a/src/objects.h b/src/objects.h
index cdf1e24..7d036eb 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -386,6 +386,17 @@
V(EXTERNAL_FLOAT_ARRAY_TYPE) \
V(EXTERNAL_DOUBLE_ARRAY_TYPE) \
V(EXTERNAL_PIXEL_ARRAY_TYPE) \
+ \
+ V(FIXED_INT8_ARRAY_TYPE) \
+ V(FIXED_UINT8_ARRAY_TYPE) \
+ V(FIXED_INT16_ARRAY_TYPE) \
+ V(FIXED_UINT16_ARRAY_TYPE) \
+ V(FIXED_INT32_ARRAY_TYPE) \
+ V(FIXED_UINT32_ARRAY_TYPE) \
+ V(FIXED_FLOAT32_ARRAY_TYPE) \
+ V(FIXED_FLOAT64_ARRAY_TYPE) \
+ V(FIXED_UINT8_CLAMPED_ARRAY_TYPE) \
+ \
V(FILLER_TYPE) \
\
V(DECLARED_ACCESSOR_DESCRIPTOR_TYPE) \
@@ -720,6 +731,17 @@
EXTERNAL_FLOAT_ARRAY_TYPE,
EXTERNAL_DOUBLE_ARRAY_TYPE,
EXTERNAL_PIXEL_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
+
+ FIXED_INT8_ARRAY_TYPE, // FIRST_FIXED_TYPED_ARRAY_TYPE
+ FIXED_UINT8_ARRAY_TYPE,
+ FIXED_INT16_ARRAY_TYPE,
+ FIXED_UINT16_ARRAY_TYPE,
+ FIXED_INT32_ARRAY_TYPE,
+ FIXED_UINT32_ARRAY_TYPE,
+ FIXED_FLOAT32_ARRAY_TYPE,
+ FIXED_FLOAT64_ARRAY_TYPE,
+ FIXED_UINT8_CLAMPED_ARRAY_TYPE, // LAST_FIXED_TYPED_ARRAY_TYPE
+
FIXED_DOUBLE_ARRAY_TYPE,
FILLER_TYPE, // LAST_DATA_TYPE
@@ -797,6 +819,9 @@
// Boundaries for testing for an external array.
FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
+ // Boundaries for testing for a fixed typed array.
+ FIRST_FIXED_TYPED_ARRAY_TYPE = FIXED_INT8_ARRAY_TYPE,
+ LAST_FIXED_TYPED_ARRAY_TYPE = FIXED_UINT8_CLAMPED_ARRAY_TYPE,
// Boundary for promotion to old data space/old pointer space.
LAST_DATA_TYPE = FILLER_TYPE,
// Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy).
@@ -989,6 +1014,16 @@
V(ExternalFloatArray) \
V(ExternalDoubleArray) \
V(ExternalPixelArray) \
+ V(FixedTypedArrayBase) \
+ V(FixedUint8Array) \
+ V(FixedInt8Array) \
+ V(FixedUint16Array) \
+ V(FixedInt16Array) \
+ V(FixedUint32Array) \
+ V(FixedInt32Array) \
+ V(FixedFloat32Array) \
+ V(FixedFloat64Array) \
+ V(FixedUint8ClampedArray) \
V(ByteArray) \
V(FreeSpace) \
V(JSReceiver) \
@@ -2109,6 +2144,7 @@
inline bool HasFastHoleyElements();
inline bool HasNonStrictArgumentsElements();
inline bool HasDictionaryElements();
+
inline bool HasExternalPixelElements();
inline bool HasExternalArrayElements();
inline bool HasExternalByteElements();
@@ -2119,6 +2155,9 @@
inline bool HasExternalUnsignedIntElements();
inline bool HasExternalFloatElements();
inline bool HasExternalDoubleElements();
+
+ inline bool HasFixedTypedArrayElements();
+
bool HasFastArgumentsElements();
bool HasDictionaryArgumentsElements();
inline SeededNumberDictionary* element_dictionary(); // Gets slow elements.
@@ -4828,6 +4867,76 @@
};
+class FixedTypedArrayBase: public FixedArrayBase {
+ public:
+ // Casting:
+ static inline FixedTypedArrayBase* cast(Object* obj);
+
+ static const int kDataOffset = kHeaderSize;
+
+ inline int size();
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArrayBase);
+};
+
+
+template <class Traits>
+class FixedTypedArray: public FixedTypedArrayBase {
+ public:
+ typedef typename Traits::ElementType ElementType;
+ static const InstanceType kInstanceType = Traits::kInstanceType;
+
+ // Casting:
+ static inline FixedTypedArray<Traits>* cast(Object* obj);
+
+ static inline int SizeFor(int length) {
+ return kDataOffset + length * sizeof(ElementType);
+ }
+
+ inline ElementType get_scalar(int index);
+ MUST_USE_RESULT inline MaybeObject* get(int index);
+ inline void set(int index, ElementType value);
+
+ // This accessor applies the correct conversion from Smi, HeapNumber
+ // and undefined.
+ MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
+
+ static Handle<Object> SetValue(Handle<FixedTypedArray<Traits> > array,
+ uint32_t index,
+ Handle<Object> value);
+
+ DECLARE_PRINTER(FixedTypedArray)
+ DECLARE_VERIFIER(FixedTypedArray)
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArray);
+};
+
+#define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType) \
+ class Type##ArrayTraits { \
+ public: \
+ typedef elementType ElementType; \
+ static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \
+ static const char* Designator() { return #type " array"; } \
+ static inline MaybeObject* ToObject(Heap* heap, elementType scalar); \
+ static elementType defaultValue() { return 0; } \
+ }; \
+ \
+ typedef FixedTypedArray<Type##ArrayTraits> Fixed##Type##Array;
+
+FIXED_TYPED_ARRAY_TRAITS(Uint8, uint8, UINT8, uint8_t)
+FIXED_TYPED_ARRAY_TRAITS(Int8, int8, INT8, int8_t)
+FIXED_TYPED_ARRAY_TRAITS(Uint16, uint16, UINT16, uint16_t)
+FIXED_TYPED_ARRAY_TRAITS(Int16, int16, INT16, int16_t)
+FIXED_TYPED_ARRAY_TRAITS(Uint32, uint32, UINT32, uint32_t)
+FIXED_TYPED_ARRAY_TRAITS(Int32, int32, INT32, int32_t)
+FIXED_TYPED_ARRAY_TRAITS(Float32, float32, FLOAT32, float)
+FIXED_TYPED_ARRAY_TRAITS(Float64, float64, FLOAT64, double)
+FIXED_TYPED_ARRAY_TRAITS(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t)
+
+#undef FIXED_TYPED_ARRAY_TRAITS
+
// DeoptimizationInputData is a fixed array used to hold the deoptimization
// data for code generated by the Hydrogen/Lithium compiler. It also
// contains information about functions that were inlined. If N different
@@ -5642,6 +5751,9 @@
void DeoptimizeDependentCodeGroup(Isolate* isolate,
DependentCode::DependencyGroup group);
+ bool MarkCodeForDeoptimization(Isolate* isolate,
+ DependentCode::DependencyGroup group);
+
// The following low-level accessors should only be used by this class
// and the mark compact collector.
inline int number_of_entries(DependencyGroup group);
@@ -5834,6 +5946,10 @@
return IsExternalArrayElementsKind(elements_kind());
}
+ inline bool has_fixed_typed_array_elements() {
+ return IsFixedTypedArrayElementsKind(elements_kind());
+ }
+
inline bool has_dictionary_elements() {
return IsDictionaryElementsKind(elements_kind());
}
diff --git a/src/runtime.cc b/src/runtime.cc
index a1f04a2..8697a91 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -5218,7 +5218,8 @@
}
js_object->ValidateElements();
- if (js_object->HasExternalArrayElements()) {
+ if (js_object->HasExternalArrayElements() ||
+ js_object->HasFixedTypedArrayElements()) {
if (!value->IsNumber() && !value->IsUndefined()) {
bool has_exception;
Handle<Object> number =
@@ -10007,6 +10008,15 @@
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT16_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT32_ELEMENTS:
+ case INT32_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
// External arrays are always dense.
return length;
}
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 38f1960..cb8d294 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -1676,7 +1676,8 @@
Handle<Map> receiver_map) {
ElementsKind elements_kind = receiver_map->elements_kind();
if (receiver_map->has_fast_elements() ||
- receiver_map->has_external_array_elements()) {
+ receiver_map->has_external_array_elements() ||
+ receiver_map->has_fixed_typed_array_elements()) {
Handle<Code> stub = KeyedLoadFastElementStub(
receiver_map->instance_type() == JS_ARRAY_TYPE,
elements_kind).GetCode(isolate());
@@ -1701,7 +1702,8 @@
bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
Handle<Code> stub;
if (receiver_map->has_fast_elements() ||
- receiver_map->has_external_array_elements()) {
+ receiver_map->has_external_array_elements() ||
+ receiver_map->has_fixed_typed_array_elements()) {
stub = KeyedStoreFastElementStub(
is_jsarray,
elements_kind,
@@ -1799,7 +1801,8 @@
ElementsKind elements_kind = receiver_map->elements_kind();
if (IsFastElementsKind(elements_kind) ||
- IsExternalArrayElementsKind(elements_kind)) {
+ IsExternalArrayElementsKind(elements_kind) ||
+ IsFixedTypedArrayElementsKind(elements_kind)) {
cached_stub =
KeyedLoadFastElementStub(is_js_array,
elements_kind).GetCode(isolate());
@@ -1842,7 +1845,8 @@
cached_stub = isolate()->builtins()->KeyedStoreIC_Slow();
} else {
if (receiver_map->has_fast_elements() ||
- receiver_map->has_external_array_elements()) {
+ receiver_map->has_external_array_elements() ||
+ receiver_map->has_fixed_typed_array_elements()) {
cached_stub = KeyedStoreFastElementStub(
is_js_array,
elements_kind,
diff --git a/src/third_party/valgrind/valgrind.h b/src/third_party/valgrind/valgrind.h
index 7a3ee2f..fa3f536 100644
--- a/src/third_party/valgrind/valgrind.h
+++ b/src/third_party/valgrind/valgrind.h
@@ -21,16 +21,16 @@
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 2. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
+ 2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
- 4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
@@ -52,13 +52,13 @@
the terms of the GNU General Public License, version 2. See the
COPYING file in the source distribution for details.
- ----------------------------------------------------------------
+ ----------------------------------------------------------------
*/
/* This file is for inclusion into client (your!) code.
- You can use these macros to manipulate and query Valgrind's
+ You can use these macros to manipulate and query Valgrind's
execution inside your own programs.
The resulting executables will still run without Valgrind, just a
@@ -194,8 +194,8 @@
this is executed not under Valgrind. Args are passed in a memory
block, and so there's no intrinsic limit to the number that could
be passed, but it's currently five.
-
- The macro args are:
+
+ The macro args are:
_zzq_rlval result lvalue
_zzq_default default value (result returned when running on real CPU)
_zzq_request request code
@@ -222,7 +222,7 @@
|| (defined(PLAT_x86_win32) && defined(__GNUC__))
typedef
- struct {
+ struct {
unsigned int nraddr; /* where's the code? */
}
OrigFn;
@@ -277,7 +277,7 @@
#if defined(PLAT_x86_win32) && !defined(__GNUC__)
typedef
- struct {
+ struct {
unsigned int nraddr; /* where's the code? */
}
OrigFn;
@@ -343,7 +343,7 @@
#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
typedef
- struct {
+ struct {
uint64_t nraddr; /* where's the code? */
}
OrigFn;
@@ -398,7 +398,7 @@
#if defined(PLAT_ppc32_linux)
typedef
- struct {
+ struct {
unsigned int nraddr; /* where's the code? */
}
OrigFn;
@@ -459,7 +459,7 @@
#if defined(PLAT_ppc64_linux)
typedef
- struct {
+ struct {
uint64_t nraddr; /* where's the code? */
uint64_t r2; /* what tocptr do we need? */
}
@@ -526,7 +526,7 @@
#if defined(PLAT_arm_linux)
typedef
- struct {
+ struct {
unsigned int nraddr; /* where's the code? */
}
OrigFn;
@@ -1709,7 +1709,7 @@
"r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
"r11", "r12", "r13"
-/* These CALL_FN_ macros assume that on ppc32-linux,
+/* These CALL_FN_ macros assume that on ppc32-linux,
sizeof(unsigned long) == 4. */
#define CALL_FN_W_v(lval, orig) \
@@ -3581,7 +3581,7 @@
#define VG_IS_TOOL_USERREQ(a, b, v) \
(VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
-/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
+/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
This enum comprises an ABI exported by Valgrind to programs
which use client requests. DO NOT CHANGE THE ORDER OF THESE
ENTRIES, NOR DELETE ANY -- add new ones at the end. */
@@ -3710,7 +3710,7 @@
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
VG_USERREQ__PRINTF_VALIST_BY_REF,
(unsigned long)format,
- (unsigned long)&vargs,
+ (unsigned long)&vargs,
0, 0, 0);
#endif
va_end(vargs);
@@ -3748,7 +3748,7 @@
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
(unsigned long)format,
- (unsigned long)&vargs,
+ (unsigned long)&vargs,
0, 0, 0);
#endif
va_end(vargs);
@@ -3759,7 +3759,7 @@
/* These requests allow control to move from the simulated CPU to the
real CPU, calling an arbitary function.
-
+
Note that the current ThreadId is inserted as the first argument.
So this call:
@@ -3845,7 +3845,7 @@
- It marks the block as being addressable and undefined (if 'is_zeroed' is
not set), or addressable and defined (if 'is_zeroed' is set). This
controls how accesses to the block by the program are handled.
-
+
'addr' is the start of the usable block (ie. after any
redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
can apply redzones -- these are blocks of padding at the start and end of
@@ -3853,7 +3853,7 @@
Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
zeroed (or filled with another predictable value), as is the case for
calloc().
-
+
VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
heap block -- that will be used by the client program -- is allocated.
It's best to put it at the outermost level of the allocator if possible;
diff --git a/src/third_party/vtune/jitprofiling.cc b/src/third_party/vtune/jitprofiling.cc
index b3952b3..4028290 100644
--- a/src/third_party/vtune/jitprofiling.cc
+++ b/src/third_party/vtune/jitprofiling.cc
@@ -103,12 +103,12 @@
/* end collector dll part. */
-/* loadiJIT_Funcs() : this function is called just in the beginning and is responsible
+/* loadiJIT_Funcs() : this function is called just in the beginning and is responsible
** to load the functions from BistroJavaCollector.dll
** result:
** on success: the functions loads, iJIT_DLL_is_missing=0, return value = 1.
** on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 0.
-*/
+*/
static int loadiJIT_Funcs(void);
/* global representing whether the BistroJavaCollector can't be loaded */
@@ -129,7 +129,7 @@
#define INIT_TOP_Stack 10000
-typedef struct
+typedef struct
{
unsigned int TopStack;
unsigned int CurrentStack;
@@ -139,9 +139,9 @@
/*
** The function for reporting virtual-machine related events to VTune.
-** Note: when reporting iJVM_EVENT_TYPE_ENTER_NIDS, there is no need to fill in the stack_id
+** Note: when reporting iJVM_EVENT_TYPE_ENTER_NIDS, there is no need to fill in the stack_id
** field in the iJIT_Method_NIDS structure, as VTune fills it.
-**
+**
** The return value in iJVM_EVENT_TYPE_ENTER_NIDS && iJVM_EVENT_TYPE_LEAVE_NIDS events
** will be 0 in case of failure.
** in iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event it will be -1 if EventSpecificData == 0
@@ -153,7 +153,7 @@
int ReturnValue;
/*******************************************************************************
- ** This section is for debugging outside of VTune.
+ ** This section is for debugging outside of VTune.
** It creates the environment variables that indicates call graph mode.
** If running outside of VTune remove the remark.
**
@@ -170,22 +170,22 @@
*******************************************************************************/
/* initialization part - the functions have not been loaded yet. This part
- ** will load the functions, and check if we are in Call Graph mode.
+ ** will load the functions, and check if we are in Call Graph mode.
** (for special treatment).
*/
- if (!FUNC_NotifyEvent)
+ if (!FUNC_NotifyEvent)
{
- if (iJIT_DLL_is_missing)
+ if (iJIT_DLL_is_missing)
return 0;
// load the Function from the DLL
- if (!loadiJIT_Funcs())
+ if (!loadiJIT_Funcs())
return 0;
/* Call Graph initialization. */
}
- /* If the event is method entry/exit, check that in the current mode
+ /* If the event is method entry/exit, check that in the current mode
** VTune is allowed to receive it
*/
if ((event_type == iJVM_EVENT_TYPE_ENTER_NIDS || event_type == iJVM_EVENT_TYPE_LEAVE_NIDS) &&
@@ -194,7 +194,7 @@
return 0;
}
/* This section is performed when method enter event occurs.
- ** It updates the virtual stack, or creates it if this is the first
+ ** It updates the virtual stack, or creates it if this is the first
** method entry in the thread. The stack pointer is decreased.
*/
if (event_type == iJVM_EVENT_TYPE_ENTER_NIDS)
@@ -263,7 +263,7 @@
return 0;
}
- ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData);
+ ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData);
return ReturnValue;
}
@@ -296,7 +296,7 @@
/* this function loads the collector dll (BistroJavaCollector) and the relevant functions.
** on success: all functions load, iJIT_DLL_is_missing = 0, return value = 1.
** on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0.
-*/
+*/
static int loadiJIT_Funcs()
{
static int bDllWasLoaded = 0;
@@ -314,7 +314,7 @@
iJIT_DLL_is_missing = 1;
FUNC_NotifyEvent = NULL;
- if (m_libHandle)
+ if (m_libHandle)
{
#if ITT_PLATFORM==ITT_PLATFORM_WIN
FreeLibrary(m_libHandle);
@@ -390,7 +390,7 @@
#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
FUNC_NotifyEvent = reinterpret_cast<TPNotify>(reinterpret_cast<intptr_t>(dlsym(m_libHandle, "NotifyEvent")));
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- if (!FUNC_NotifyEvent)
+ if (!FUNC_NotifyEvent)
{
FUNC_Initialize = NULL;
return 0;
@@ -401,7 +401,7 @@
#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
FUNC_Initialize = reinterpret_cast<TPInitialize>(reinterpret_cast<intptr_t>(dlsym(m_libHandle, "Initialize")));
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- if (!FUNC_Initialize)
+ if (!FUNC_Initialize)
{
FUNC_NotifyEvent = NULL;
return 0;
@@ -433,7 +433,7 @@
}
/*
-** This function should be called by the user whenever a thread ends, to free the thread
+** This function should be called by the user whenever a thread ends, to free the thread
** "virtual stack" storage
*/
ITT_EXTERN_C void JITAPI FinalizeThread()
@@ -464,7 +464,7 @@
*/
ITT_EXTERN_C void JITAPI FinalizeProcess()
{
- if (m_libHandle)
+ if (m_libHandle)
{
#if ITT_PLATFORM==ITT_PLATFORM_WIN
FreeLibrary(m_libHandle);
@@ -484,7 +484,7 @@
/*
** This function should be called by the user for any method once.
-** The function will return a unique method ID, the user should maintain the ID for each
+** The function will return a unique method ID, the user should maintain the ID for each
** method
*/
ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID()
diff --git a/src/third_party/vtune/jitprofiling.h b/src/third_party/vtune/jitprofiling.h
index abd6d8c..193f243 100644
--- a/src/third_party/vtune/jitprofiling.h
+++ b/src/third_party/vtune/jitprofiling.h
@@ -67,54 +67,54 @@
{
/* shutdown */
-
- /*
+
+ /*
* Program exiting EventSpecificData NA
*/
- iJVM_EVENT_TYPE_SHUTDOWN = 2,
+ iJVM_EVENT_TYPE_SHUTDOWN = 2,
/* JIT profiling */
-
- /*
+
+ /*
* issued after method code jitted into memory but before code is executed
* EventSpecificData is an iJIT_Method_Load
*/
- iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED=13,
+ iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED=13,
- /* issued before unload. Method code will no longer be executed, but code
- * and info are still in memory. The VTune profiler may capture method
+ /* issued before unload. Method code will no longer be executed, but code
+ * and info are still in memory. The VTune profiler may capture method
* code only at this point EventSpecificData is iJIT_Method_Id
*/
- iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
+ iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
/* Method Profiling */
- /* method name, Id and stack is supplied
- * issued when a method is about to be entered EventSpecificData is
+ /* method name, Id and stack is supplied
+ * issued when a method is about to be entered EventSpecificData is
* iJIT_Method_NIDS
*/
- iJVM_EVENT_TYPE_ENTER_NIDS = 19,
+ iJVM_EVENT_TYPE_ENTER_NIDS = 19,
- /* method name, Id and stack is supplied
- * issued when a method is about to be left EventSpecificData is
+ /* method name, Id and stack is supplied
+ * issued when a method is about to be left EventSpecificData is
* iJIT_Method_NIDS
*/
- iJVM_EVENT_TYPE_LEAVE_NIDS
+ iJVM_EVENT_TYPE_LEAVE_NIDS
} iJIT_JVM_EVENT;
typedef enum _iJIT_ModeFlags
{
/* No need to Notify VTune, since VTune is not running */
- iJIT_NO_NOTIFICATIONS = 0x0000,
+ iJIT_NO_NOTIFICATIONS = 0x0000,
- /* when turned on the jit must call
+ /* when turned on the jit must call
* iJIT_NotifyEvent
* (
* iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
* )
* for all the method already jitted
*/
- iJIT_BE_NOTIFY_ON_LOAD = 0x0001,
+ iJIT_BE_NOTIFY_ON_LOAD = 0x0001,
/* when turned on the jit must call
* iJIT_NotifyEvent
@@ -122,19 +122,19 @@
* iJVM_EVENT_TYPE_METHOD_UNLOAD_FINISHED,
* ) for all the method that are unloaded
*/
- iJIT_BE_NOTIFY_ON_UNLOAD = 0x0002,
+ iJIT_BE_NOTIFY_ON_UNLOAD = 0x0002,
/* when turned on the jit must instrument all
* the currently jited code with calls on
* method entries
*/
- iJIT_BE_NOTIFY_ON_METHOD_ENTRY = 0x0004,
+ iJIT_BE_NOTIFY_ON_METHOD_ENTRY = 0x0004,
/* when turned on the jit must instrument all
* the currently jited code with calls
* on method exit
*/
- iJIT_BE_NOTIFY_ON_METHOD_EXIT = 0x0008
+ iJIT_BE_NOTIFY_ON_METHOD_EXIT = 0x0008
} iJIT_ModeFlags;
@@ -143,13 +143,13 @@
typedef enum _iJIT_IsProfilingActiveFlags
{
/* No profiler is running. Currently not used */
- iJIT_NOTHING_RUNNING = 0x0000,
+ iJIT_NOTHING_RUNNING = 0x0000,
/* Sampling is running. This is the default value
* returned by iJIT_IsProfilingActive()
*/
- iJIT_SAMPLING_ON = 0x0001,
-
+ iJIT_SAMPLING_ON = 0x0001,
+
/* Call Graph is running */
iJIT_CALLGRAPH_ON = 0x0002
@@ -174,7 +174,7 @@
/* Id of the method (same as the one passed in
* the iJIT_Method_Load struct
*/
- unsigned int method_id;
+ unsigned int method_id;
} *piJIT_Method_Id, iJIT_Method_Id;
@@ -188,13 +188,13 @@
typedef struct _iJIT_Method_NIDS
{
/* unique method ID */
- unsigned int method_id;
+ unsigned int method_id;
/* NOTE: no need to fill this field, it's filled by VTune */
- unsigned int stack_id;
+ unsigned int stack_id;
/* method name (just the method, without the class) */
- char* method_name;
+ char* method_name;
} *piJIT_Method_NIDS, iJIT_Method_NIDS;
/* structures for the events:
@@ -204,54 +204,54 @@
typedef struct _LineNumberInfo
{
/* x86 Offset from the begining of the method*/
- unsigned int Offset;
-
+ unsigned int Offset;
+
/* source line number from the begining of the source file */
- unsigned int LineNumber;
+ unsigned int LineNumber;
} *pLineNumberInfo, LineNumberInfo;
typedef struct _iJIT_Method_Load
{
/* unique method ID - can be any unique value, (except 0 - 999) */
- unsigned int method_id;
+ unsigned int method_id;
/* method name (can be with or without the class and signature, in any case
* the class name will be added to it)
*/
- char* method_name;
+ char* method_name;
/* virtual address of that method - This determines the method range for the
* iJVM_EVENT_TYPE_ENTER/LEAVE_METHOD_ADDR events
*/
- void* method_load_address;
+ void* method_load_address;
/* Size in memory - Must be exact */
- unsigned int method_size;
+ unsigned int method_size;
/* Line Table size in number of entries - Zero if none */
- unsigned int line_number_size;
-
+ unsigned int line_number_size;
+
/* Pointer to the begining of the line numbers info array */
- pLineNumberInfo line_number_table;
+ pLineNumberInfo line_number_table;
/* unique class ID */
- unsigned int class_id;
-
+ unsigned int class_id;
+
/* class file name */
- char* class_file_name;
+ char* class_file_name;
/* source file name */
- char* source_file_name;
+ char* source_file_name;
/* bits supplied by the user for saving in the JIT file */
- void* user_data;
+ void* user_data;
/* the size of the user data buffer */
- unsigned int user_data_size;
+ unsigned int user_data_size;
/* NOTE: no need to fill this field, it's filled by VTune */
- iJDEnvironmentType env;
+ iJDEnvironmentType env;
} *piJIT_Method_Load, iJIT_Method_Load;
@@ -280,7 +280,7 @@
int JITAPI iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData);
/* The new mode call back routine */
-void JITAPI iJIT_RegisterCallbackEx(void *userdata,
+void JITAPI iJIT_RegisterCallbackEx(void *userdata,
iJIT_ModeChangedEx NewModeCallBackFuncEx);
iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive(void);
diff --git a/src/third_party/vtune/v8-vtune.h b/src/third_party/vtune/v8-vtune.h
index 29ea3ea..c60b303 100644
--- a/src/third_party/vtune/v8-vtune.h
+++ b/src/third_party/vtune/v8-vtune.h
@@ -1,38 +1,38 @@
/*
This file is provided under a dual BSD/GPLv2 license. When using or
redistributing this file, you may do so under either license.
-
+
GPL LICENSE SUMMARY
-
+
Copyright(c) 2005-2012 Intel Corporation. All rights reserved.
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
-
+
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution
in the file called LICENSE.GPL.
-
+
Contact Information:
http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
-
+
BSD LICENSE
-
+
Copyright(c) 2005-2012 Intel Corporation. All rights reserved.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
-
+
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
@@ -42,7 +42,7 @@
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/src/third_party/vtune/vtune-jit.cc b/src/third_party/vtune/vtune-jit.cc
index 93de7ef..ea897e5 100644
--- a/src/third_party/vtune/vtune-jit.cc
+++ b/src/third_party/vtune/vtune-jit.cc
@@ -193,7 +193,7 @@
jmethod.method_name = temp_method_name;
Handle<Script> script = event->script;
-
+
if (*script != NULL) {
// Get the source file name and set it to jmethod.source_file_name
if ((*script->GetScriptName())->IsString()) {
@@ -228,7 +228,7 @@
}
GetEntries()->erase(event->code_start);
}
- }
+ }
iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
reinterpret_cast<void*>(&jmethod));
@@ -261,11 +261,11 @@
case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
GetEntries()->insert(std::pair <void*, void*>(event->code_start, event->user_data));
break;
- }
+ }
default:
break;
}
- }
+ }
return;
}
diff --git a/src/third_party/vtune/vtune-jit.h b/src/third_party/vtune/vtune-jit.h
index 42b8c3d..15011bf 100644
--- a/src/third_party/vtune/vtune-jit.h
+++ b/src/third_party/vtune/vtune-jit.h
@@ -1,38 +1,38 @@
/*
This file is provided under a dual BSD/GPLv2 license. When using or
redistributing this file, you may do so under either license.
-
+
GPL LICENSE SUMMARY
-
+
Copyright(c) 2005-2012 Intel Corporation. All rights reserved.
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
-
+
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution
in the file called LICENSE.GPL.
-
+
Contact Information:
http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
-
+
BSD LICENSE
-
+
Copyright(c) 2005-2012 Intel Corporation. All rights reserved.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
-
+
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
@@ -42,7 +42,7 @@
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/src/version.cc b/src/version.cc
index f31096f..d299d77 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 24
-#define BUILD_NUMBER 17
+#define BUILD_NUMBER 18
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 910d760..4585fa7 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -1305,9 +1305,19 @@
void Assembler::load_rax(void* value, RelocInfo::Mode mode) {
EnsureSpace ensure_space(this);
- emit(0x48); // REX.W
- emit(0xA1);
- emitp(value, mode);
+ if (kPointerSize == kInt64Size) {
+ emit(0x48); // REX.W
+ emit(0xA1);
+ emitp(value, mode);
+ } else {
+ ASSERT(kPointerSize == kInt32Size);
+ emit(0xA1);
+ emitp(value, mode);
+ // In 64-bit mode, need to zero extend the operand to 8 bytes.
+ // See 2.2.1.4 in Intel64 and IA32 Architectures Software
+ // Developer's Manual Volume 2.
+ emitl(0);
+ }
}
@@ -1888,9 +1898,19 @@
void Assembler::store_rax(void* dst, RelocInfo::Mode mode) {
EnsureSpace ensure_space(this);
- emit(0x48); // REX.W
- emit(0xA3);
- emitp(dst, mode);
+ if (kPointerSize == kInt64Size) {
+ emit(0x48); // REX.W
+ emit(0xA3);
+ emitp(dst, mode);
+ } else {
+ ASSERT(kPointerSize == kInt32Size);
+ emit(0xA3);
+ emitp(dst, mode);
+ // In 64-bit mode, need to zero extend the operand to 8 bytes.
+ // See 2.2.1.4 in Intel64 and IA32 Architectures Software
+ // Developer's Manual Volume 2.
+ emitl(0);
+ }
}
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 51282c2..84e86fe 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -50,9 +50,7 @@
deopt_mode_(mode) { }
virtual ~SafepointGenerator() {}
- virtual void BeforeCall(int call_size) const V8_OVERRIDE {
- codegen_->EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - call_size);
- }
+ virtual void BeforeCall(int call_size) const V8_OVERRIDE {}
virtual void AfterCall() const V8_OVERRIDE {
codegen_->RecordSafepoint(pointers_, deopt_mode_);
@@ -602,7 +600,6 @@
LInstruction* instr,
SafepointMode safepoint_mode,
int argc) {
- EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - masm()->CallSize(code));
ASSERT(instr != NULL);
__ call(code, mode);
RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc);
@@ -2966,39 +2963,51 @@
__ movsxlq(key_reg, key_reg);
}
}
+ int base_offset = instr->is_fixed_typed_array()
+ ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
+ : 0;
Operand operand(BuildFastArrayOperand(
instr->elements(),
key,
elements_kind,
- 0,
+ base_offset,
instr->additional_index()));
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS) {
XMMRegister result(ToDoubleRegister(instr->result()));
__ movss(result, operand);
__ cvtss2sd(result, result);
- } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+ } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
+ elements_kind == FLOAT64_ELEMENTS) {
__ movsd(ToDoubleRegister(instr->result()), operand);
} else {
Register result(ToRegister(instr->result()));
switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
+ case INT8_ELEMENTS:
__ movsxbq(result, operand);
break;
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
__ movzxbq(result, operand);
break;
case EXTERNAL_SHORT_ELEMENTS:
+ case INT16_ELEMENTS:
__ movsxwq(result, operand);
break;
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case UINT16_ELEMENTS:
__ movzxwq(result, operand);
break;
case EXTERNAL_INT_ELEMENTS:
+ case INT32_ELEMENTS:
__ movsxlq(result, operand);
break;
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case UINT32_ELEMENTS:
__ movl(result, operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ testl(result, result);
@@ -3007,6 +3016,8 @@
break;
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
case FAST_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@@ -3114,7 +3125,7 @@
void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
- if (instr->is_external()) {
+ if (instr->is_typed_elements()) {
DoLoadKeyedExternalArray(instr);
} else if (instr->hydrogen()->representation().IsDouble()) {
DoLoadKeyedFixedDoubleArray(instr);
@@ -4145,18 +4156,23 @@
__ movsxlq(key_reg, key_reg);
}
}
+ int base_offset = instr->is_fixed_typed_array()
+ ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
+ : 0;
Operand operand(BuildFastArrayOperand(
instr->elements(),
key,
elements_kind,
- 0,
+ base_offset,
instr->additional_index()));
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS) {
XMMRegister value(ToDoubleRegister(instr->value()));
__ cvtsd2ss(value, value);
__ movss(operand, value);
- } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+ } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
+ elements_kind == FLOAT64_ELEMENTS) {
__ movsd(operand, ToDoubleRegister(instr->value()));
} else {
Register value(ToRegister(instr->value()));
@@ -4164,18 +4180,27 @@
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case INT8_ELEMENTS:
+ case UINT8_ELEMENTS:
+ case UINT8_CLAMPED_ELEMENTS:
__ movb(operand, value);
break;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case INT16_ELEMENTS:
+ case UINT16_ELEMENTS:
__ movw(operand, value);
break;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case INT32_ELEMENTS:
+ case UINT32_ELEMENTS:
__ movl(operand, value);
break;
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
+ case FLOAT32_ELEMENTS:
+ case FLOAT64_ELEMENTS:
case FAST_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@@ -4307,7 +4332,7 @@
void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
- if (instr->is_external()) {
+ if (instr->is_typed_elements()) {
DoStoreKeyedExternalArray(instr);
} else if (instr->hydrogen()->value()->representation().IsDouble()) {
DoStoreKeyedFixedDoubleArray(instr);
@@ -5414,20 +5439,21 @@
void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
- if (info()->IsStub()) return;
- // Ensure that we have enough space after the previous lazy-bailout
- // instruction for patching the code here.
- int current_pc = masm()->pc_offset();
- if (current_pc < last_lazy_deopt_pc_ + space_needed) {
- int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
- __ Nop(padding_size);
+ if (!info()->IsStub()) {
+ // Ensure that we have enough space after the previous lazy-bailout
+ // instruction for patching the code here.
+ int current_pc = masm()->pc_offset();
+ if (current_pc < last_lazy_deopt_pc_ + space_needed) {
+ int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
+ __ Nop(padding_size);
+ }
}
+ last_lazy_deopt_pc_ = masm()->pc_offset();
}
void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
- last_lazy_deopt_pc_ = masm()->pc_offset();
ASSERT(instr->HasEnvironment());
LEnvironment* env = instr->environment();
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
@@ -5500,7 +5526,6 @@
RelocInfo::CODE_TARGET,
instr);
EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
- last_lazy_deopt_pc_ = masm()->pc_offset();
__ bind(&done);
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
@@ -5512,7 +5537,6 @@
__ CompareRoot(rsp, Heap::kStackLimitRootIndex);
__ j(below, deferred_stack_check->entry());
EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
- last_lazy_deopt_pc_ = masm()->pc_offset();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 849e99e..2e760a3 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -2033,24 +2033,23 @@
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
- if (!instr->is_external()) {
+ if (!instr->is_typed_elements()) {
LOperand* obj = UseRegisterAtStart(instr->elements());
result = new(zone()) LLoadKeyed(obj, key);
} else {
ASSERT(
(instr->representation().IsInteger32() &&
- (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
- (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+ !(IsDoubleOrFloatElementsKind(instr->elements_kind()))) ||
(instr->representation().IsDouble() &&
- ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
- (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
- LOperand* external_pointer = UseRegister(instr->elements());
- result = new(zone()) LLoadKeyed(external_pointer, key);
+ (IsDoubleOrFloatElementsKind(instr->elements_kind()))));
+ LOperand* backing_store = UseRegister(instr->elements());
+ result = new(zone()) LLoadKeyed(backing_store, key);
}
DefineAsRegister(result);
bool can_deoptimize = instr->RequiresHoleCheck() ||
- (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
+ (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) ||
+ (elements_kind == UINT32_ELEMENTS);
// An unsigned int array load might overflow and cause a deopt, make sure it
// has an environment.
return can_deoptimize ? AssignEnvironment(result) : result;
@@ -2071,7 +2070,7 @@
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
- if (!instr->is_external()) {
+ if (!instr->is_typed_elements()) {
ASSERT(instr->elements()->representation().IsTagged());
bool needs_write_barrier = instr->NeedsWriteBarrier();
LOperand* object = NULL;
@@ -2101,21 +2100,23 @@
}
ASSERT(
- (instr->value()->representation().IsInteger32() &&
- (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
- (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
- (instr->value()->representation().IsDouble() &&
- ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
- (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
- ASSERT(instr->elements()->representation().IsExternal());
+ (instr->value()->representation().IsInteger32() &&
+ !IsDoubleOrFloatElementsKind(elements_kind)) ||
+ (instr->value()->representation().IsDouble() &&
+ IsDoubleOrFloatElementsKind(elements_kind)));
+ ASSERT((instr->is_fixed_typed_array() &&
+ instr->elements()->representation().IsTagged()) ||
+ (instr->is_external() &&
+ instr->elements()->representation().IsExternal()));
bool val_is_temp_register =
elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
- elements_kind == EXTERNAL_FLOAT_ELEMENTS;
+ elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS;
LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
: UseRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
- LOperand* external_pointer = UseRegister(instr->elements());
- return new(zone()) LStoreKeyed(external_pointer, key, val);
+ LOperand* backing_store = UseRegister(instr->elements());
+ return new(zone()) LStoreKeyed(backing_store, key, val);
}
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index f337e9f..61b4965 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -1540,6 +1540,12 @@
bool is_external() const {
return hydrogen()->is_external();
}
+ bool is_fixed_typed_array() const {
+ return hydrogen()->is_fixed_typed_array();
+ }
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
@@ -2167,6 +2173,12 @@
}
bool is_external() const { return hydrogen()->is_external(); }
+ bool is_fixed_typed_array() const {
+ return hydrogen()->is_fixed_typed_array();
+ }
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 66ffc9a..d8b714c 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -16113,14 +16113,6 @@
result = CompileRun("ext_array[1]");
CHECK_EQ(1, result->Int32Value());
- // Check pass through of assigned smis
- result = CompileRun("var sum = 0;"
- "for (var i = 0; i < 8; i++) {"
- " sum += ext_array[i] = ext_array[i] = -i;"
- "}"
- "sum;");
- CHECK_EQ(-28, result->Int32Value());
-
// Check assigned smis
result = CompileRun("for (var i = 0; i < 8; i++) {"
" ext_array[i] = i;"
@@ -16130,7 +16122,16 @@
" sum += ext_array[i];"
"}"
"sum;");
+
CHECK_EQ(28, result->Int32Value());
+ // Check pass through of assigned smis
+ result = CompileRun("var sum = 0;"
+ "for (var i = 0; i < 8; i++) {"
+ " sum += ext_array[i] = ext_array[i] = -i;"
+ "}"
+ "sum;");
+ CHECK_EQ(-28, result->Int32Value());
+
// Check assigned smis in reverse order
result = CompileRun("for (var i = 8; --i >= 0; ) {"
@@ -16398,6 +16399,113 @@
}
+template <class FixedTypedArrayClass,
+ i::ElementsKind elements_kind,
+ class ElementType>
+static void FixedTypedArrayTestHelper(
+ v8::ExternalArrayType array_type,
+ ElementType low,
+ ElementType high) {
+ i::FLAG_allow_natives_syntax = true;
+ LocalContext context;
+ i::Isolate* isolate = CcTest::i_isolate();
+ i::Factory* factory = isolate->factory();
+ v8::HandleScope scope(context->GetIsolate());
+ const int kElementCount = 260;
+ i::Handle<FixedTypedArrayClass> fixed_array =
+ i::Handle<FixedTypedArrayClass>::cast(
+ factory->NewFixedTypedArray(kElementCount, array_type));
+ CHECK_EQ(FixedTypedArrayClass::kInstanceType,
+ fixed_array->map()->instance_type());
+ CHECK_EQ(kElementCount, fixed_array->length());
+ CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ for (int i = 0; i < kElementCount; i++) {
+ fixed_array->set(i, static_cast<ElementType>(i));
+ }
+ // Force GC to trigger verification.
+ CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+ for (int i = 0; i < kElementCount; i++) {
+ CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
+ static_cast<int64_t>(fixed_array->get_scalar(i)));
+ }
+ v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
+ i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
+ i::Handle<i::Map> fixed_array_map =
+ isolate->factory()->GetElementsTransitionMap(jsobj, elements_kind);
+ jsobj->set_map(*fixed_array_map);
+ jsobj->set_elements(*fixed_array);
+
+ ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
+ context.local(), obj, kElementCount, array_type,
+ static_cast<int64_t>(low),
+ static_cast<int64_t>(high));
+}
+
+
+THREADED_TEST(FixedUint8Array) {
+ FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
+ v8::kExternalUnsignedByteArray,
+ 0x0, 0xFF);
+}
+
+
+THREADED_TEST(FixedUint8ClampedArray) {
+ FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
+ i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
+ v8::kExternalPixelArray,
+ 0x0, 0xFF);
+}
+
+
+THREADED_TEST(FixedInt8Array) {
+ FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
+ v8::kExternalByteArray,
+ -0x80, 0x7F);
+}
+
+
+THREADED_TEST(FixedUint16Array) {
+ FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
+ v8::kExternalUnsignedShortArray,
+ 0x0, 0xFFFF);
+}
+
+
+THREADED_TEST(FixedInt16Array) {
+ FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
+ v8::kExternalShortArray,
+ -0x8000, 0x7FFF);
+}
+
+
+THREADED_TEST(FixedUint32Array) {
+ FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
+ v8::kExternalUnsignedIntArray,
+ 0x0, UINT_MAX);
+}
+
+
+THREADED_TEST(FixedInt32Array) {
+ FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
+ v8::kExternalIntArray,
+ INT_MIN, INT_MAX);
+}
+
+
+THREADED_TEST(FixedFloat32Array) {
+ FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
+ v8::kExternalFloatArray,
+ -500, 500);
+}
+
+
+THREADED_TEST(FixedFloat64Array) {
+ FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
+ v8::kExternalDoubleArray,
+ -500, 500);
+}
+
+
template <class ExternalArrayClass, class ElementType>
static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
int64_t low,
diff --git a/tools/merge-to-branch.sh b/tools/merge-to-branch.sh
index 2df24c1..175567e 100755
--- a/tools/merge-to-branch.sh
+++ b/tools/merge-to-branch.sh
@@ -243,7 +243,9 @@
git checkout $BRANCHNAME \
|| die "cannot ensure that the current branch is $BRANCHNAME"
wait_for_lgtm
- PRESUBMIT_TREE_CHECK="skip" git cl dcommit \
+ PRESUBMIT_TREE_CHECK="skip" git cl presubmit \
+ || die "presubmit failed"
+ PRESUBMIT_TREE_CHECK="skip" git cl dcommit --bypass-hooks \
|| die "failed to commit to $MERGE_TO_BRANCH"
fi