Version 3.27.11 (based on bleeding_edge revision r21445)
Add support for ES6 Symbol in heap profiler (Chromium issue 376194).
Performance and stability improvements on all platforms.
git-svn-id: https://v8.googlecode.com/svn/trunk@21446 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 61efe5f..706a17b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2014-05-23: Version 3.27.11
+
+ Add support for ES6 Symbol in heap profiler (Chromium issue 376194).
+
+ Performance and stability improvements on all platforms.
+
+
2014-05-22: Version 3.27.10
Implement Mirror object for Symbols (issue 3290).
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index 306a0ef..7fc193d 100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -219,19 +219,20 @@
class V8_EXPORT HeapGraphNode {
public:
enum Type {
- kHidden = 0, // Hidden node, may be filtered when shown to user.
- kArray = 1, // An array of elements.
- kString = 2, // A string.
- kObject = 3, // A JS object (except for arrays and strings).
- kCode = 4, // Compiled code.
- kClosure = 5, // Function closure.
- kRegExp = 6, // RegExp.
- kHeapNumber = 7, // Number stored in the heap.
- kNative = 8, // Native object (not from V8 heap).
- kSynthetic = 9, // Synthetic object, usualy used for grouping
- // snapshot items together.
- kConsString = 10, // Concatenated string. A pair of pointers to strings.
- kSlicedString = 11 // Sliced string. A fragment of another string.
+ kHidden = 0, // Hidden node, may be filtered when shown to user.
+ kArray = 1, // An array of elements.
+ kString = 2, // A string.
+ kObject = 3, // A JS object (except for arrays and strings).
+ kCode = 4, // Compiled code.
+ kClosure = 5, // Function closure.
+ kRegExp = 6, // RegExp.
+ kHeapNumber = 7, // Number stored in the heap.
+ kNative = 8, // Native object (not from V8 heap).
+ kSynthetic = 9, // Synthetic object, usualy used for grouping
+ // snapshot items together.
+ kConsString = 10, // Concatenated string. A pair of pointers to strings.
+ kSlicedString = 11, // Sliced string. A fragment of another string.
+ kSymbol = 12 // A Symbol (ES6).
};
/** Returns node type (see HeapGraphNode::Type). */
diff --git a/include/v8.h b/include/v8.h
index 8c2aaf9..bfd3de0 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2097,7 +2097,7 @@
bool Set(uint32_t index, Handle<Value> value);
- // Sets a local property on this object bypassing interceptors and
+ // Sets an own property on this object bypassing interceptors and
// overriding accessors or read-only properties.
//
// Note that if the object has an interceptor the property will be set
diff --git a/samples/lineprocessor.cc b/samples/lineprocessor.cc
index 6f8fd35..edb0ba0 100644
--- a/samples/lineprocessor.cc
+++ b/samples/lineprocessor.cc
@@ -69,25 +69,6 @@
var res = line + " | " + line;
print(res);
}
-
- *
- * When run with "-p" argument, the program starts V8 Debugger Agent and
- * allows remote debugger to attach and debug JavaScript code.
- *
- * Interesting aspects:
- * 1. Wait for remote debugger to attach
- * Normally the program compiles custom script and immediately runs it.
- * If programmer needs to debug script from the very beginning, he should
- * run this sample program with "--wait-for-connection" command line parameter.
- * This way V8 will suspend on the first statement and wait for
- * debugger to attach.
- *
- * 2. Unresponsive V8
- * V8 Debugger Agent holds a connection with remote debugger, but it does
- * respond only when V8 is running some script. In particular, when this program
- * is waiting for input, all requests from debugger get deferred until V8
- * is called again. See how "--callback" command-line parameter in this sample
- * fixes this issue.
*/
enum MainCycleType {
@@ -113,7 +94,6 @@
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
v8::Isolate* isolate = v8::Isolate::New();
v8::Isolate::Scope isolate_scope(isolate);
- v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::String> script_source;
@@ -224,7 +204,6 @@
v8::Local<v8::Context> context,
bool report_exceptions) {
v8::Isolate* isolate = context->GetIsolate();
- v8::Locker lock(isolate);
v8::Handle<v8::String> fun_name =
v8::String::NewFromUtf8(isolate, "ProcessLine");
@@ -382,7 +361,6 @@
char* res;
{
- v8::Unlocker unlocker(v8::Isolate::GetCurrent());
res = fgets(buffer, kBufferSize, stdin);
}
v8::Isolate* isolate = v8::Isolate::GetCurrent();
diff --git a/src/accessors.cc b/src/accessors.cc
index 6f2c01b..6245613 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -183,7 +183,7 @@
// causes an infinite loop.
if (!object->IsJSArray()) {
MaybeHandle<Object> maybe_result =
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
object, isolate->factory()->length_string(), value, NONE);
maybe_result.Check();
return;
@@ -790,7 +790,7 @@
if (!function->should_have_prototype()) {
// Since we hit this accessor, object will have no prototype property.
MaybeHandle<Object> maybe_result =
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
receiver, isolate->factory()->prototype_string(), value, NONE);
return maybe_result.ToHandleChecked();
}
diff --git a/src/api.cc b/src/api.cc
index 304d84f..c33365b 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -5,10 +5,10 @@
#include "api.h"
#include <string.h> // For memcpy, strlen.
-#include <cmath> // For isnan.
#ifdef V8_USE_ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif // V8_USE_ADDRESS_SANITIZER
+#include <cmath> // For isnan.
#include "../include/v8-debug.h"
#include "../include/v8-profiler.h"
#include "../include/v8-testing.h"
@@ -1750,12 +1750,10 @@
Source* source,
CompileOptions options) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
- ON_BAILOUT(isolate, "v8::ScriptCompiler::Compile()",
- return Local<Script>());
+ ON_BAILOUT(isolate, "v8::ScriptCompiler::Compile()", return Local<Script>());
LOG_API(isolate, "ScriptCompiler::CompiletBound()");
ENTER_V8(isolate);
- Local<UnboundScript> generic =
- CompileUnbound(v8_isolate, source, options);
+ Local<UnboundScript> generic = CompileUnbound(v8_isolate, source, options);
if (generic.IsEmpty()) return Local<Script>();
return generic->BindToCurrentContext();
}
@@ -3059,8 +3057,8 @@
bool v8::Object::SetPrivate(v8::Handle<Private> key, v8::Handle<Value> value) {
- return Set(v8::Handle<Value>(reinterpret_cast<Value*>(*key)),
- value, DontEnum);
+ return ForceSet(v8::Handle<Value>(reinterpret_cast<Value*>(*key)),
+ value, DontEnum);
}
@@ -3147,8 +3145,7 @@
Local<Value> v8::Object::GetPrototype() {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
- ON_BAILOUT(isolate, "v8::Object::GetPrototype()",
- return Local<v8::Value>());
+ ON_BAILOUT(isolate, "v8::Object::GetPrototype()", return Local<v8::Value>());
ENTER_V8(isolate);
i::Handle<i::Object> self = Utils::OpenHandle(this);
i::Handle<i::Object> result(self->GetPrototype(isolate), isolate);
@@ -3224,7 +3221,7 @@
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::FixedArray> value;
has_pending_exception = !i::JSReceiver::GetKeys(
- self, i::JSReceiver::LOCAL_ONLY).ToHandle(&value);
+ self, i::JSReceiver::OWN_ONLY).ToHandle(&value);
EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
// Because we use caching to speed up enumeration it is important
// to never change the result of the basic enumeration function so
@@ -3349,6 +3346,8 @@
bool v8::Object::HasPrivate(v8::Handle<Private> key) {
+ // TODO(rossberg): this should use HasOwnProperty, but we'd need to
+ // generalise that to a (noy yet existant) Name argument first.
return Has(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
}
@@ -3452,7 +3451,7 @@
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()",
return false);
- return i::JSReceiver::HasLocalProperty(
+ return i::JSReceiver::HasOwnProperty(
Utils::OpenHandle(this), Utils::OpenHandle(*key));
}
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index afea875..585108b 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -2934,11 +2934,13 @@
}
-void CallFunctionStub::Generate(MacroAssembler* masm) {
+static void CallFunctionNoFeedback(MacroAssembler* masm,
+ int argc, bool needs_checks,
+ bool call_as_method) {
// r1 : the function to call
Label slow, non_function, wrap, cont;
- if (NeedsChecks()) {
+ if (needs_checks) {
// Check that the function is really a JavaScript function.
// r1: pushed function (to be verified)
__ JumpIfSmi(r1, &non_function);
@@ -2950,18 +2952,17 @@
// Fast-case: Invoke the function now.
// r1: pushed function
- int argc = argc_;
ParameterCount actual(argc);
- if (CallAsMethod()) {
- if (NeedsChecks()) {
+ if (call_as_method) {
+ if (needs_checks) {
EmitContinueIfStrictOrNative(masm, &cont);
}
// Compute the receiver in sloppy mode.
__ ldr(r3, MemOperand(sp, argc * kPointerSize));
- if (NeedsChecks()) {
+ if (needs_checks) {
__ JumpIfSmi(r3, &wrap);
__ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
__ b(lt, &wrap);
@@ -2974,19 +2975,24 @@
__ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper());
- if (NeedsChecks()) {
+ if (needs_checks) {
// Slow-case: Non-function called.
__ bind(&slow);
EmitSlowCase(masm, argc, &non_function);
}
- if (CallAsMethod()) {
+ if (call_as_method) {
__ bind(&wrap);
EmitWrapCase(masm, argc, &cont);
}
}
+void CallFunctionStub::Generate(MacroAssembler* masm) {
+ CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod());
+}
+
+
void CallConstructStub::Generate(MacroAssembler* masm) {
// r0 : number of arguments
// r1 : the function to call
@@ -3046,7 +3052,7 @@
__ bind(&do_call);
// Set expected number of arguments to zero (not changing r0).
__ mov(r2, Operand::Zero());
- __ Jump(isolate()->builtins()->ArgumentsAdaptorTrampoline(),
+ __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET);
}
@@ -3060,6 +3066,51 @@
}
+void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
+ // r1 - function
+ // r2 - feedback vector
+ // r3 - slot id
+ __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4);
+ __ cmp(r1, r4);
+ __ b(ne, miss);
+
+ __ mov(r0, Operand(arg_count()));
+ __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
+ __ ldr(r2, FieldMemOperand(r4, FixedArray::kHeaderSize));
+ // Verify that r2 contains an AllocationSite
+ __ AssertUndefinedOrAllocationSite(r2, r4);
+ ArrayConstructorStub stub(masm->isolate(), arg_count());
+ __ TailCallStub(&stub);
+}
+
+
+void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) {
+ // r1 - function
+ // r2 - feedback vector
+ // r3 - slot id
+ Label miss;
+
+ if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) {
+ Generate_MonomorphicArray(masm, &miss);
+ } else {
+ // So far there is only one customer for our custom feedback scheme.
+ UNREACHABLE();
+ }
+
+ __ bind(&miss);
+ GenerateMiss(masm);
+
+ // The slow case, we need this no matter what to complete a call after a miss.
+ CallFunctionNoFeedback(masm,
+ arg_count(),
+ true,
+ CallAsMethod());
+
+ // Unreachable.
+ __ stop("Unexpected code address");
+}
+
+
void CallICStub::Generate(MacroAssembler* masm) {
// r1 - function
// r3 - slot id (Smi)
@@ -3071,6 +3122,11 @@
EmitLoadTypeFeedbackVector(masm, r2);
+ if (state_.stub_type() != CallIC::DEFAULT) {
+ Generate_CustomFeedbackCall(masm);
+ return;
+ }
+
// The checks. First, does r1 match the recorded monomorphic target?
__ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
__ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize));
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index c3270f0..0325774 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -148,7 +148,7 @@
// jumping to the target address intended by the caller and that was
// overwritten by the address of DebugBreakXXX.
ExternalReference after_break_target =
- ExternalReference(Debug_Address::AfterBreakTarget(), masm->isolate());
+ ExternalReference::debug_after_break_target_address(masm->isolate());
__ mov(ip, Operand(after_break_target));
__ ldr(ip, MemOperand(ip));
__ Jump(ip);
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 7a4de9f..1e54695 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -337,7 +337,7 @@
stream->Add("[");
key()->PrintTo(stream);
if (hydrogen()->IsDehoisted()) {
- stream->Add(" + %d]", additional_index());
+ stream->Add(" + %d]", base_offset());
} else {
stream->Add("]");
}
@@ -349,7 +349,7 @@
stream->Add("[");
key()->PrintTo(stream);
if (hydrogen()->IsDehoisted()) {
- stream->Add(" + %d] <-", additional_index());
+ stream->Add(" + %d] <-", base_offset());
} else {
stream->Add("] <- ");
}
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index b333095..714ec55 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -1648,7 +1648,7 @@
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- uint32_t additional_index() const { return hydrogen()->index_offset(); }
+ uint32_t base_offset() const { return hydrogen()->base_offset(); }
};
@@ -2223,7 +2223,7 @@
}
return hydrogen()->NeedsCanonicalization();
}
- uint32_t additional_index() const { return hydrogen()->index_offset(); }
+ uint32_t base_offset() const { return hydrogen()->base_offset(); }
};
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 623a9dc..d2e665e 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -3168,17 +3168,13 @@
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 = IsFixedTypedArrayElementsKind(elements_kind)
- ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
- : 0;
-
+ int base_offset = instr->base_offset();
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS ||
elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
- int base_offset =
- (instr->additional_index() << element_size_shift) + additional_offset;
+ int base_offset = instr->base_offset();
DwVfpRegister result = ToDoubleRegister(instr->result());
Operand operand = key_is_constant
? Operand(constant_key << element_size_shift)
@@ -3188,15 +3184,14 @@
elements_kind == FLOAT32_ELEMENTS) {
__ vldr(double_scratch0().low(), scratch0(), base_offset);
__ vcvt_f64_f32(result, double_scratch0().low());
- } else { // loading doubles, not floats.
+ } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
__ vldr(result, scratch0(), base_offset);
}
} else {
Register result = ToRegister(instr->result());
MemOperand mem_operand = PrepareKeyedOperand(
key, external_pointer, key_is_constant, constant_key,
- element_size_shift, shift_size,
- instr->additional_index(), additional_offset);
+ element_size_shift, shift_size, base_offset);
switch (elements_kind) {
case EXTERNAL_INT8_ELEMENTS:
case INT8_ELEMENTS:
@@ -3256,15 +3251,13 @@
int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
- int base_offset =
- FixedDoubleArray::kHeaderSize - kHeapObjectTag +
- (instr->additional_index() << element_size_shift);
+ int base_offset = instr->base_offset();
if (key_is_constant) {
int constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
Abort(kArrayIndexConstantValueTooBig);
}
- base_offset += constant_key << element_size_shift;
+ base_offset += constant_key * kDoubleSize;
}
__ add(scratch, elements, Operand(base_offset));
@@ -3290,12 +3283,11 @@
Register result = ToRegister(instr->result());
Register scratch = scratch0();
Register store_base = scratch;
- int offset = 0;
+ int offset = instr->base_offset();
if (instr->key()->IsConstantOperand()) {
LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
- offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
- instr->additional_index());
+ offset += ToInteger32(const_operand) * kPointerSize;
store_base = elements;
} else {
Register key = ToRegister(instr->key());
@@ -3308,9 +3300,8 @@
} else {
__ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
}
- offset = FixedArray::OffsetOfElementAt(instr->additional_index());
}
- __ ldr(result, FieldMemOperand(store_base, offset));
+ __ ldr(result, MemOperand(store_base, offset));
// Check for the hole value.
if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -3343,32 +3334,12 @@
int constant_key,
int element_size,
int shift_size,
- int additional_index,
- int additional_offset) {
- int base_offset = (additional_index << element_size) + additional_offset;
+ int base_offset) {
if (key_is_constant) {
- return MemOperand(base,
- base_offset + (constant_key << element_size));
+ return MemOperand(base, (constant_key << element_size) + base_offset);
}
- 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);
- // key can be negative, so using ASR here.
- __ add(scratch0(), scratch0(), Operand(key, ASR, 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) {
+ if (base_offset == 0) {
if (shift_size >= 0) {
return MemOperand(base, key, LSL, shift_size);
} else {
@@ -3378,10 +3349,12 @@
}
if (shift_size >= 0) {
- return MemOperand(base, scratch0(), LSL, shift_size);
+ __ add(scratch0(), base, Operand(key, LSL, shift_size));
+ return MemOperand(scratch0(), base_offset);
} else {
ASSERT_EQ(-1, shift_size);
- return MemOperand(base, scratch0(), LSR, 1);
+ __ add(scratch0(), base, Operand(key, ASR, 1));
+ return MemOperand(scratch0(), base_offset);
}
}
@@ -4211,16 +4184,12 @@
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 = IsFixedTypedArrayElementsKind(elements_kind)
- ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
- : 0;
+ int base_offset = instr->base_offset();
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS ||
elements_kind == EXTERNAL_FLOAT64_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) {
@@ -4245,7 +4214,7 @@
MemOperand mem_operand = PrepareKeyedOperand(
key, external_pointer, key_is_constant, constant_key,
element_size_shift, shift_size,
- instr->additional_index(), additional_offset);
+ base_offset);
switch (elements_kind) {
case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
case EXTERNAL_INT8_ELEMENTS:
@@ -4292,6 +4261,7 @@
Register scratch = scratch0();
DwVfpRegister double_scratch = double_scratch0();
bool key_is_constant = instr->key()->IsConstantOperand();
+ int base_offset = instr->base_offset();
// Calculate the effective address of the slot in the array to store the
// double value.
@@ -4302,13 +4272,11 @@
Abort(kArrayIndexConstantValueTooBig);
}
__ add(scratch, elements,
- Operand((constant_key << element_size_shift) +
- FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+ Operand((constant_key << element_size_shift) + base_offset));
} else {
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
- __ add(scratch, elements,
- Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+ __ add(scratch, elements, Operand(base_offset));
__ add(scratch, scratch,
Operand(ToRegister(instr->key()), LSL, shift_size));
}
@@ -4321,10 +4289,9 @@
__ Assert(ne, kDefaultNaNModeNotSet);
}
__ VFPCanonicalizeNaN(double_scratch, value);
- __ vstr(double_scratch, scratch,
- instr->additional_index() << element_size_shift);
+ __ vstr(double_scratch, scratch, 0);
} else {
- __ vstr(value, scratch, instr->additional_index() << element_size_shift);
+ __ vstr(value, scratch, 0);
}
}
@@ -4336,14 +4303,13 @@
: no_reg;
Register scratch = scratch0();
Register store_base = scratch;
- int offset = 0;
+ int offset = instr->base_offset();
// Do the store.
if (instr->key()->IsConstantOperand()) {
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
- offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
- instr->additional_index());
+ offset += ToInteger32(const_operand) * kPointerSize;
store_base = elements;
} else {
// Even though the HLoadKeyed instruction forces the input
@@ -4355,16 +4321,15 @@
} else {
__ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
}
- offset = FixedArray::OffsetOfElementAt(instr->additional_index());
}
- __ str(value, FieldMemOperand(store_base, offset));
+ __ str(value, MemOperand(store_base, offset));
if (instr->hydrogen()->NeedsWriteBarrier()) {
SmiCheck check_needed =
instr->hydrogen()->value()->IsHeapObject()
? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
// Compute address of modified element and store it into key register.
- __ add(key, store_base, Operand(offset - kHeapObjectTag));
+ __ add(key, store_base, Operand(offset));
__ RecordWrite(elements,
key,
value,
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 3e05c32..d541b8e 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -133,8 +133,7 @@
int constant_key,
int element_size,
int shift_size,
- int additional_index,
- int additional_offset);
+ int base_offset);
// Emit frame translation commands for an environment.
void WriteTranslation(LEnvironment* environment, Translation* translation);
diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc
index 0bf89d8..d1185b2 100644
--- a/src/arm64/code-stubs-arm64.cc
+++ b/src/arm64/code-stubs-arm64.cc
@@ -3217,10 +3217,10 @@
}
-void CallFunctionStub::Generate(MacroAssembler* masm) {
- ASM_LOCATION("CallFunctionStub::Generate");
+static void CallFunctionNoFeedback(MacroAssembler* masm,
+ int argc, bool needs_checks,
+ bool call_as_method) {
// x1 function the function to call
-
Register function = x1;
Register type = x4;
Label slow, non_function, wrap, cont;
@@ -3228,7 +3228,7 @@
// TODO(jbramley): This function has a lot of unnamed registers. Name them,
// and tidy things up a bit.
- if (NeedsChecks()) {
+ if (needs_checks) {
// Check that the function is really a JavaScript function.
__ JumpIfSmi(function, &non_function);
@@ -3238,18 +3238,17 @@
// Fast-case: Invoke the function now.
// x1 function pushed function
- int argc = argc_;
ParameterCount actual(argc);
- if (CallAsMethod()) {
- if (NeedsChecks()) {
+ if (call_as_method) {
+ if (needs_checks) {
EmitContinueIfStrictOrNative(masm, &cont);
}
// Compute the receiver in sloppy mode.
__ Peek(x3, argc * kPointerSize);
- if (NeedsChecks()) {
+ if (needs_checks) {
__ JumpIfSmi(x3, &wrap);
__ JumpIfObjectType(x3, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt);
} else {
@@ -3263,20 +3262,25 @@
actual,
JUMP_FUNCTION,
NullCallWrapper());
-
- if (NeedsChecks()) {
+ if (needs_checks) {
// Slow-case: Non-function called.
__ Bind(&slow);
EmitSlowCase(masm, argc, function, type, &non_function);
}
- if (CallAsMethod()) {
+ if (call_as_method) {
__ Bind(&wrap);
EmitWrapCase(masm, argc, &cont);
}
}
+void CallFunctionStub::Generate(MacroAssembler* masm) {
+ ASM_LOCATION("CallFunctionStub::Generate");
+ CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod());
+}
+
+
void CallConstructStub::Generate(MacroAssembler* masm) {
ASM_LOCATION("CallConstructStub::Generate");
// x0 : number of arguments
@@ -3356,6 +3360,59 @@
}
+void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
+ // x1 - function
+ // x2 - feedback vector
+ // x3 - slot id
+ Register function = x1;
+ Register feedback_vector = x2;
+ Register index = x3;
+ Register scratch = x4;
+
+ __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch);
+ __ Cmp(function, scratch);
+ __ B(ne, miss);
+
+ Register allocation_site = feedback_vector;
+ __ Mov(x0, Operand(arg_count()));
+
+ __ Add(scratch, feedback_vector,
+ Operand::UntagSmiAndScale(index, kPointerSizeLog2));
+ __ Ldr(allocation_site, FieldMemOperand(scratch, FixedArray::kHeaderSize));
+
+ // Verify that x2 contains an AllocationSite
+ __ AssertUndefinedOrAllocationSite(allocation_site, scratch);
+ ArrayConstructorStub stub(masm->isolate(), arg_count());
+ __ TailCallStub(&stub);
+}
+
+
+void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) {
+ // x1 - function
+ // x2 - feedback vector
+ // x3 - slot id
+ Label miss;
+
+ if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) {
+ Generate_MonomorphicArray(masm, &miss);
+ } else {
+ // So far there is only one customer for our custom feedback scheme.
+ UNREACHABLE();
+ }
+
+ __ bind(&miss);
+ GenerateMiss(masm);
+
+ // The slow case, we need this no matter what to complete a call after a miss.
+ CallFunctionNoFeedback(masm,
+ arg_count(),
+ true,
+ CallAsMethod());
+
+ __ Unreachable();
+}
+
+
void CallICStub::Generate(MacroAssembler* masm) {
ASM_LOCATION("CallICStub");
@@ -3374,6 +3431,11 @@
EmitLoadTypeFeedbackVector(masm, feedback_vector);
+ if (state_.stub_type() != CallIC::DEFAULT) {
+ Generate_CustomFeedbackCall(masm);
+ return;
+ }
+
// The checks. First, does x1 match the recorded monomorphic target?
__ Add(x4, feedback_vector,
Operand::UntagSmiAndScale(index, kPointerSizeLog2));
diff --git a/src/arm64/debug-arm64.cc b/src/arm64/debug-arm64.cc
index 6b18967..e781c28 100644
--- a/src/arm64/debug-arm64.cc
+++ b/src/arm64/debug-arm64.cc
@@ -207,8 +207,8 @@
// Now that the break point has been handled, resume normal execution by
// jumping to the target address intended by the caller and that was
// overwritten by the address of DebugBreakXXX.
- ExternalReference after_break_target(Debug_Address::AfterBreakTarget(),
- masm->isolate());
+ ExternalReference after_break_target =
+ ExternalReference::debug_after_break_target_address(masm->isolate());
__ Mov(scratch, after_break_target);
__ Ldr(scratch, MemOperand(scratch));
__ Br(scratch);
diff --git a/src/arm64/lithium-arm64.h b/src/arm64/lithium-arm64.h
index 85629c4..7bd2c5ad 100644
--- a/src/arm64/lithium-arm64.h
+++ b/src/arm64/lithium-arm64.h
@@ -1757,15 +1757,15 @@
bool is_typed_elements() const {
return is_external() || is_fixed_typed_array();
}
- uint32_t additional_index() const {
- return this->hydrogen()->index_offset();
+ uint32_t base_offset() const {
+ return this->hydrogen()->base_offset();
}
void PrintDataTo(StringStream* stream) V8_OVERRIDE {
this->elements()->PrintTo(stream);
stream->Add("[");
this->key()->PrintTo(stream);
- if (this->hydrogen()->IsDehoisted()) {
- stream->Add(" + %d]", this->additional_index());
+ if (this->base_offset() != 0) {
+ stream->Add(" + %d]", this->base_offset());
} else {
stream->Add("]");
}
@@ -2419,14 +2419,14 @@
}
return this->hydrogen()->NeedsCanonicalization();
}
- uint32_t additional_index() const { return this->hydrogen()->index_offset(); }
+ uint32_t base_offset() const { return this->hydrogen()->base_offset(); }
void PrintDataTo(StringStream* stream) V8_OVERRIDE {
this->elements()->PrintTo(stream);
stream->Add("[");
this->key()->PrintTo(stream);
- if (this->hydrogen()->IsDehoisted()) {
- stream->Add(" + %d] <-", this->additional_index());
+ if (this->base_offset() != 0) {
+ stream->Add(" + %d] <-", this->base_offset());
} else {
stream->Add("] <- ");
}
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc
index dab60e5..4ecc434 100644
--- a/src/arm64/lithium-codegen-arm64.cc
+++ b/src/arm64/lithium-codegen-arm64.cc
@@ -3373,29 +3373,25 @@
bool key_is_constant,
int constant_key,
ElementsKind elements_kind,
- int additional_index) {
+ int base_offset) {
int element_size_shift = ElementsKindToShiftSize(elements_kind);
- int additional_offset = additional_index << element_size_shift;
- if (IsFixedTypedArrayElementsKind(elements_kind)) {
- additional_offset += FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
- }
if (key_is_constant) {
int key_offset = constant_key << element_size_shift;
- return MemOperand(base, key_offset + additional_offset);
+ return MemOperand(base, key_offset + base_offset);
}
if (key_is_smi) {
__ Add(scratch, base, Operand::UntagSmiAndScale(key, element_size_shift));
- return MemOperand(scratch, additional_offset);
+ return MemOperand(scratch, base_offset);
}
- if (additional_offset == 0) {
+ if (base_offset == 0) {
return MemOperand(base, key, SXTW, element_size_shift);
}
ASSERT(!AreAliased(scratch, key));
- __ Add(scratch, base, additional_offset);
+ __ Add(scratch, base, base_offset);
return MemOperand(scratch, key, SXTW, element_size_shift);
}
@@ -3424,7 +3420,7 @@
PrepareKeyedExternalArrayOperand(key, ext_ptr, scratch, key_is_smi,
key_is_constant, constant_key,
elements_kind,
- instr->additional_index());
+ instr->base_offset());
if ((elements_kind == EXTERNAL_FLOAT32_ELEMENTS) ||
(elements_kind == FLOAT32_ELEMENTS)) {
@@ -3495,7 +3491,7 @@
bool key_is_tagged,
ElementsKind elements_kind,
Representation representation,
- int additional_index) {
+ int base_offset) {
STATIC_ASSERT((kSmiValueSize == 32) && (kSmiShift == 32) && (kSmiTag == 0));
int element_size_shift = ElementsKindToShiftSize(elements_kind);
@@ -3509,9 +3505,9 @@
ASSERT(elements_kind == FAST_SMI_ELEMENTS);
// Read or write only the most-significant 32 bits in the case of fast smi
// arrays.
- return UntagSmiFieldMemOperand(base, additional_index);
+ return UntagSmiMemOperand(base, base_offset);
} else {
- return FieldMemOperand(base, additional_index);
+ return MemOperand(base, base_offset);
}
} else {
// Sign extend key because it could be a 32-bit negative value or contain
@@ -3522,9 +3518,9 @@
// Read or write only the most-significant 32 bits in the case of fast smi
// arrays.
__ Add(base, elements, Operand(key, SXTW, element_size_shift));
- return UntagSmiFieldMemOperand(base, additional_index);
+ return UntagSmiMemOperand(base, base_offset);
} else {
- __ Add(base, elements, additional_index - kHeapObjectTag);
+ __ Add(base, elements, base_offset);
return MemOperand(base, key, SXTW, element_size_shift);
}
}
@@ -3544,18 +3540,16 @@
if (constant_key & 0xf0000000) {
Abort(kArrayIndexConstantValueTooBig);
}
- int offset = FixedDoubleArray::OffsetOfElementAt(constant_key +
- instr->additional_index());
- mem_op = FieldMemOperand(elements, offset);
+ int offset = instr->base_offset() + constant_key * kDoubleSize;
+ mem_op = MemOperand(elements, offset);
} else {
Register load_base = ToRegister(instr->temp());
Register key = ToRegister(instr->key());
bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi();
- int offset = FixedDoubleArray::OffsetOfElementAt(instr->additional_index());
mem_op = PrepareKeyedArrayOperand(load_base, elements, key, key_is_tagged,
instr->hydrogen()->elements_kind(),
instr->hydrogen()->representation(),
- offset);
+ instr->base_offset());
}
__ Ldr(result, mem_op);
@@ -3581,25 +3575,24 @@
if (instr->key()->IsConstantOperand()) {
ASSERT(instr->temp() == NULL);
LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
- int offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
- instr->additional_index());
+ int offset = instr->base_offset() +
+ ToInteger32(const_operand) * kPointerSize;
if (representation.IsInteger32()) {
ASSERT(instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS);
STATIC_ASSERT((kSmiValueSize == 32) && (kSmiShift == 32) &&
(kSmiTag == 0));
- mem_op = UntagSmiFieldMemOperand(elements, offset);
+ mem_op = UntagSmiMemOperand(elements, offset);
} else {
- mem_op = FieldMemOperand(elements, offset);
+ mem_op = MemOperand(elements, offset);
}
} else {
Register load_base = ToRegister(instr->temp());
Register key = ToRegister(instr->key());
bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi();
- int offset = FixedArray::OffsetOfElementAt(instr->additional_index());
mem_op = PrepareKeyedArrayOperand(load_base, elements, key, key_is_tagged,
instr->hydrogen()->elements_kind(),
- representation, offset);
+ representation, instr->base_offset());
}
__ Load(result, mem_op, representation);
@@ -5137,7 +5130,7 @@
PrepareKeyedExternalArrayOperand(key, ext_ptr, scratch, key_is_smi,
key_is_constant, constant_key,
elements_kind,
- instr->additional_index());
+ instr->base_offset());
if ((elements_kind == EXTERNAL_FLOAT32_ELEMENTS) ||
(elements_kind == FLOAT32_ELEMENTS)) {
@@ -5202,18 +5195,16 @@
if (constant_key & 0xf0000000) {
Abort(kArrayIndexConstantValueTooBig);
}
- int offset = FixedDoubleArray::OffsetOfElementAt(constant_key +
- instr->additional_index());
- mem_op = FieldMemOperand(elements, offset);
+ int offset = instr->base_offset() + constant_key * kDoubleSize;
+ mem_op = MemOperand(elements, offset);
} else {
Register store_base = ToRegister(instr->temp());
Register key = ToRegister(instr->key());
bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi();
- int offset = FixedDoubleArray::OffsetOfElementAt(instr->additional_index());
mem_op = PrepareKeyedArrayOperand(store_base, elements, key, key_is_tagged,
instr->hydrogen()->elements_kind(),
instr->hydrogen()->representation(),
- offset);
+ instr->base_offset());
}
if (instr->NeedsCanonicalization()) {
@@ -5241,27 +5232,26 @@
Representation representation = instr->hydrogen()->value()->representation();
if (instr->key()->IsConstantOperand()) {
LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
- int offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
- instr->additional_index());
+ int offset = instr->base_offset() +
+ ToInteger32(const_operand) * kPointerSize;
store_base = elements;
if (representation.IsInteger32()) {
ASSERT(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY);
ASSERT(instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS);
STATIC_ASSERT((kSmiValueSize == 32) && (kSmiShift == 32) &&
(kSmiTag == 0));
- mem_op = UntagSmiFieldMemOperand(store_base, offset);
+ mem_op = UntagSmiMemOperand(store_base, offset);
} else {
- mem_op = FieldMemOperand(store_base, offset);
+ mem_op = MemOperand(store_base, offset);
}
} else {
store_base = scratch;
key = ToRegister(instr->key());
bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi();
- int offset = FixedArray::OffsetOfElementAt(instr->additional_index());
mem_op = PrepareKeyedArrayOperand(store_base, elements, key, key_is_tagged,
instr->hydrogen()->elements_kind(),
- representation, offset);
+ representation, instr->base_offset());
}
__ Store(value, mem_op, representation);
diff --git a/src/arm64/lithium-codegen-arm64.h b/src/arm64/lithium-codegen-arm64.h
index 8c25e63..6ee2ec8 100644
--- a/src/arm64/lithium-codegen-arm64.h
+++ b/src/arm64/lithium-codegen-arm64.h
@@ -255,14 +255,14 @@
bool key_is_constant,
int constant_key,
ElementsKind elements_kind,
- int additional_index);
+ int base_offset);
MemOperand PrepareKeyedArrayOperand(Register base,
Register elements,
Register key,
bool key_is_tagged,
ElementsKind elements_kind,
Representation representation,
- int additional_index);
+ int base_offset);
void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
Safepoint::DeoptMode mode);
diff --git a/src/array.js b/src/array.js
index 5b036e6..ef7aae4 100644
--- a/src/array.js
+++ b/src/array.js
@@ -271,7 +271,7 @@
function SimpleSlice(array, start_i, del_count, len, deleted_elements) {
for (var i = 0; i < del_count; i++) {
var index = start_i + i;
- // The spec could also be interpreted such that %HasLocalProperty
+ // The spec could also be interpreted such that %HasOwnProperty
// would be the appropriate test. We follow KJS in consulting the
// prototype.
var current = array[index];
@@ -291,7 +291,7 @@
var from_index = i + del_count - 1;
var to_index = i + num_additional_args - 1;
// The spec could also be interpreted such that
- // %HasLocalProperty would be the appropriate test. We follow
+ // %HasOwnProperty would be the appropriate test. We follow
// KJS in consulting the prototype.
var current = array[from_index];
if (!IS_UNDEFINED(current) || from_index in array) {
@@ -305,7 +305,7 @@
var from_index = i + del_count;
var to_index = i + num_additional_args;
// The spec could also be interpreted such that
- // %HasLocalProperty would be the appropriate test. We follow
+ // %HasOwnProperty would be the appropriate test. We follow
// KJS in consulting the prototype.
var current = array[from_index];
if (!IS_UNDEFINED(current) || from_index in array) {
@@ -628,7 +628,7 @@
var num_arguments = %_ArgumentsLength();
var is_sealed = ObjectIsSealed(array);
- if (IS_ARRAY(array) && !is_sealed) {
+ if (IS_ARRAY(array) && !is_sealed && len > 0) {
SmartMove(array, 0, 0, len, num_arguments);
} else {
SimpleMove(array, 0, 0, len, num_arguments);
@@ -1075,7 +1075,7 @@
// For compatibility with JSC, we also sort elements inherited from
// the prototype chain on non-Array objects.
// We do this by copying them to this object and sorting only
- // local elements. This is not very efficient, but sorting with
+ // own elements. This is not very efficient, but sorting with
// inherited elements happens very, very rarely, if at all.
// The specification allows "implementation dependent" behavior
// if an element on the prototype chain has an element that
diff --git a/src/assembler.cc b/src/assembler.cc
index 103ca13..3cb4929 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -124,7 +124,8 @@
enabled_cpu_features_(0),
emit_debug_code_(FLAG_debug_code),
predictable_code_size_(false),
- serializer_enabled_(Serializer::enabled(isolate)) {
+ // We may use the assembler without an isolate.
+ serializer_enabled_(isolate && isolate->serializer_enabled()) {
if (FLAG_mask_constants_with_cookie && isolate != NULL) {
jit_cookie_ = isolate->random_number_generator()->NextInt();
}
@@ -996,9 +997,6 @@
Isolate* isolate)
: address_(Redirect(isolate, ic_utility.address())) {}
-ExternalReference::ExternalReference(const Debug_Address& debug_address,
- Isolate* isolate)
- : address_(debug_address.address(isolate)) {}
ExternalReference::ExternalReference(StatsCounter* counter)
: address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
@@ -1431,6 +1429,20 @@
}
+ExternalReference ExternalReference::debug_after_break_target_address(
+ Isolate* isolate) {
+ return ExternalReference(isolate->debug()->after_break_target_address());
+}
+
+
+ExternalReference
+ ExternalReference::debug_restarter_frame_function_pointer_address(
+ Isolate* isolate) {
+ return ExternalReference(
+ isolate->debug()->restarter_frame_function_pointer_address());
+}
+
+
double power_helper(double x, double y) {
int y_int = static_cast<int>(y);
if (y == y_int) {
diff --git a/src/assembler.h b/src/assembler.h
index 6d67fc1..2d9bde6 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -794,8 +794,6 @@
ExternalReference(const IC_Utility& ic_utility, Isolate* isolate);
- ExternalReference(const Debug_Address& debug_address, Isolate* isolate);
-
explicit ExternalReference(StatsCounter* counter);
ExternalReference(Isolate::AddressId id, Isolate* isolate);
@@ -915,6 +913,10 @@
static ExternalReference cpu_features();
+ static ExternalReference debug_after_break_target_address(Isolate* isolate);
+ static ExternalReference debug_restarter_frame_function_pointer_address(
+ Isolate* isolate);
+
static ExternalReference is_profiling_address(Isolate* isolate);
static ExternalReference invoke_function_callback(Isolate* isolate);
static ExternalReference invoke_accessor_getter_callback(Isolate* isolate);
diff --git a/src/ast.h b/src/ast.h
index 0115d98..e2ea933 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1762,11 +1762,25 @@
return !target_.is_null();
}
+ bool global_call() const {
+ VariableProxy* proxy = expression_->AsVariableProxy();
+ return proxy != NULL && proxy->var()->IsUnallocated();
+ }
+
+ bool known_global_function() const {
+ return global_call() && !target_.is_null();
+ }
+
Handle<JSFunction> target() { return target_; }
Handle<Cell> cell() { return cell_; }
+ Handle<AllocationSite> allocation_site() { return allocation_site_; }
+
void set_target(Handle<JSFunction> target) { target_ = target; }
+ void set_allocation_site(Handle<AllocationSite> site) {
+ allocation_site_ = site;
+ }
bool ComputeGlobalTarget(Handle<GlobalObject> global, LookupResult* lookup);
BailoutId ReturnId() const { return return_id_; }
@@ -1809,6 +1823,7 @@
Handle<JSFunction> target_;
Handle<Cell> cell_;
+ Handle<AllocationSite> allocation_site_;
int call_feedback_slot_;
const BailoutId return_id_;
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 551a04a..0803522 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -371,7 +371,7 @@
} else {
attributes = DONT_ENUM;
}
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
target, internalized_name, function, attributes).Check();
if (target->IsJSGlobalObject()) {
function->shared()->set_instance_class_name(*internalized_name);
@@ -748,7 +748,7 @@
Handle<JSObject> prototype =
Handle<JSObject>(
JSObject::cast(js_global_function->instance_prototype()));
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
prototype, factory()->constructor_string(),
isolate()->object_function(), NONE).Check();
} else {
@@ -863,7 +863,7 @@
Heap* heap = isolate->heap();
Handle<String> object_name = factory->Object_string();
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
inner_global, object_name,
isolate->object_function(), DONT_ENUM).Check();
@@ -1064,7 +1064,7 @@
cons->SetInstanceClassName(*name);
Handle<JSObject> json_object = factory->NewJSObject(cons, TENURED);
ASSERT(json_object->IsJSObject());
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
global, name, json_object, DONT_ENUM).Check();
native_context()->set_json_object(*json_object);
}
@@ -1130,22 +1130,22 @@
native_context()->set_sloppy_arguments_boilerplate(*result);
// Note: length must be added as the first property and
// callee must be added as the second property.
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
result, factory->length_string(),
factory->undefined_value(), DONT_ENUM,
Object::FORCE_TAGGED, FORCE_FIELD).Check();
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
result, factory->callee_string(),
factory->undefined_value(), DONT_ENUM,
Object::FORCE_TAGGED, FORCE_FIELD).Check();
#ifdef DEBUG
LookupResult lookup(isolate);
- result->LocalLookup(factory->callee_string(), &lookup);
+ result->LookupOwn(factory->callee_string(), &lookup);
ASSERT(lookup.IsField());
ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsCalleeIndex);
- result->LocalLookup(factory->length_string(), &lookup);
+ result->LookupOwn(factory->length_string(), &lookup);
ASSERT(lookup.IsField());
ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsLengthIndex);
@@ -1235,13 +1235,13 @@
native_context()->set_strict_arguments_boilerplate(*result);
// Add length property only for strict mode boilerplate.
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
result, factory->length_string(),
factory->undefined_value(), DONT_ENUM).Check();
#ifdef DEBUG
LookupResult lookup(isolate);
- result->LocalLookup(factory->length_string(), &lookup);
+ result->LookupOwn(factory->length_string(), &lookup);
ASSERT(lookup.IsField());
ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsLengthIndex);
@@ -1694,11 +1694,11 @@
Handle<String> global_string =
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("global"));
Handle<Object> global_obj(native_context()->global_object(), isolate());
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
builtins, global_string, global_obj, attributes).Check();
Handle<String> builtins_string =
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("builtins"));
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
builtins, builtins_string, builtins, attributes).Check();
// Set up the reference from the global object to the builtins object.
@@ -2148,7 +2148,7 @@
factory->InternalizeUtf8String(FLAG_expose_natives_as);
RETURN_ON_EXCEPTION_VALUE(
isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
global, natives, Handle<JSObject>(global->builtins()), DONT_ENUM),
false);
}
@@ -2162,7 +2162,7 @@
Smi::FromInt(FLAG_stack_trace_limit), isolate);
RETURN_ON_EXCEPTION_VALUE(
isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
Handle<JSObject>::cast(Error), name, stack_trace_limit, NONE),
false);
}
@@ -2183,7 +2183,7 @@
Handle<Object> global_proxy(debug_context->global_proxy(), isolate);
RETURN_ON_EXCEPTION_VALUE(
isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
global, debug_string, global_proxy, DONT_ENUM),
false);
}
@@ -2410,7 +2410,7 @@
ASSERT(!descs->GetDetails(i).representation().IsDouble());
Handle<Object> value = Handle<Object>(from->RawFastPropertyAt(index),
isolate());
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
to, key, value, details.attributes()).Check();
break;
}
@@ -2418,14 +2418,14 @@
HandleScope inner(isolate());
Handle<Name> key = Handle<Name>(descs->GetKey(i));
Handle<Object> constant(descs->GetConstant(i), isolate());
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
to, key, constant, details.attributes()).Check();
break;
}
case CALLBACKS: {
LookupResult result(isolate());
Handle<Name> key(Name::cast(descs->GetKey(i)), isolate());
- to->LocalLookup(key, &result);
+ to->LookupOwn(key, &result);
// If the property is already there we skip it
if (result.IsFound()) continue;
HandleScope inner(isolate());
@@ -2458,7 +2458,7 @@
// If the property is already there we skip it.
LookupResult result(isolate());
Handle<Name> key(Name::cast(raw_key));
- to->LocalLookup(key, &result);
+ to->LookupOwn(key, &result);
if (result.IsFound()) continue;
// Set the property.
Handle<Object> value = Handle<Object>(properties->ValueAt(i),
@@ -2469,7 +2469,7 @@
isolate());
}
PropertyDetails details = properties->DetailsAt(i);
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
to, key, value, details.attributes()).Check();
}
}
@@ -2522,8 +2522,8 @@
class NoTrackDoubleFieldsForSerializerScope {
public:
explicit NoTrackDoubleFieldsForSerializerScope(Isolate* isolate)
- : isolate_(isolate), flag_(FLAG_track_double_fields) {
- if (Serializer::enabled(isolate)) {
+ : flag_(FLAG_track_double_fields) {
+ if (isolate->serializer_enabled()) {
// Disable tracking double fields because heap numbers treated as
// immutable by the serializer.
FLAG_track_double_fields = false;
@@ -2531,13 +2531,10 @@
}
~NoTrackDoubleFieldsForSerializerScope() {
- if (Serializer::enabled(isolate_)) {
- FLAG_track_double_fields = flag_;
- }
+ FLAG_track_double_fields = flag_;
}
private:
- Isolate* isolate_;
bool flag_;
};
@@ -2614,7 +2611,7 @@
// We can't (de-)serialize typed arrays currently, but we are lucky: The state
// of the random number generator needs no initialization during snapshot
// creation time and we don't need trigonometric functions then.
- if (!Serializer::enabled(isolate)) {
+ if (!isolate->serializer_enabled()) {
// Initially seed the per-context random number generator using the
// per-isolate random number generator.
const int num_elems = 2;
@@ -2688,7 +2685,7 @@
}
-// Archive statics that are thread local.
+// Archive statics that are thread-local.
char* Bootstrapper::ArchiveState(char* to) {
*reinterpret_cast<NestingCounterType*>(to) = nesting_;
nesting_ = 0;
@@ -2696,7 +2693,7 @@
}
-// Restore statics that are thread local.
+// Restore statics that are thread-local.
char* Bootstrapper::RestoreState(char* from) {
nesting_ = *reinterpret_cast<NestingCounterType*>(from);
return from + sizeof(NestingCounterType);
diff --git a/src/builtins.cc b/src/builtins.cc
index 50eaa6f..6cdd4a9 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -382,15 +382,17 @@
}
Handle<JSArray> array = Handle<JSArray>::cast(receiver);
+ int len = Smi::cast(array->length())->value();
+ int to_add = args.length() - 1;
+ if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
+ return CallJsBuiltin(isolate, "ArrayPush", args);
+ }
ASSERT(!array->map()->is_observed());
ElementsKind kind = array->GetElementsKind();
if (IsFastSmiOrObjectElementsKind(kind)) {
Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
-
- int len = Smi::cast(array->length())->value();
- int to_add = args.length() - 1;
if (to_add == 0) {
return Smi::FromInt(len);
}
@@ -429,10 +431,7 @@
array->set_length(Smi::FromInt(new_length));
return Smi::FromInt(new_length);
} else {
- int len = Smi::cast(array->length())->value();
int elms_len = elms_obj->length();
-
- int to_add = args.length() - 1;
if (to_add == 0) {
return Smi::FromInt(len);
}
@@ -578,8 +577,6 @@
if (!array->HasFastSmiOrObjectElements()) {
return CallJsBuiltin(isolate, "ArrayUnshift", args);
}
- Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
-
int len = Smi::cast(array->length())->value();
int to_add = args.length() - 1;
int new_length = len + to_add;
@@ -587,6 +584,12 @@
// we should never hit this case.
ASSERT(to_add <= (Smi::kMaxValue - len));
+ if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
+ return CallJsBuiltin(isolate, "ArrayUnshift", args);
+ }
+
+ Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
+
JSObject::EnsureCanContainElements(array, &args, 1, to_add,
DONT_ALLOW_DOUBLE_ELEMENTS);
diff --git a/src/code-stubs.h b/src/code-stubs.h
index fbd0c2b..6d77fc3 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -822,6 +822,8 @@
// Code generation helpers.
void GenerateMiss(MacroAssembler* masm);
+ void Generate_CustomFeedbackCall(MacroAssembler* masm);
+ void Generate_MonomorphicArray(MacroAssembler* masm, Label* miss);
CallIC::State state_;
};
diff --git a/src/compiler.cc b/src/compiler.cc
index 2873525..4e55d22 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -456,6 +456,8 @@
if (optimized_code.is_null()) {
if (info()->bailout_reason() == kNoReason) {
info_->set_bailout_reason(kCodeGenerationFailed);
+ } else if (info()->bailout_reason() == kMapBecameUnstable) {
+ return AbortOptimization();
}
return AbortAndDisableOptimization();
}
@@ -518,7 +520,7 @@
// TODO(yangguo): check whether those heuristics are still up-to-date.
// We do not shrink objects that go into a snapshot (yet), so we adjust
// the estimate conservatively.
- if (Serializer::enabled(shared->GetIsolate())) {
+ if (shared->GetIsolate()->serializer_enabled()) {
estimate += 2;
} else if (FLAG_clever_optimizations) {
// Inobject slack tracking will reclaim redundant inobject space later,
diff --git a/src/contexts.cc b/src/contexts.cc
index 58ae49a..1d0e2f8 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -108,7 +108,7 @@
// to only do a local lookup for context extension objects.
if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 ||
object->IsJSContextExtensionObject()) {
- *attributes = JSReceiver::GetLocalPropertyAttribute(object, name);
+ *attributes = JSReceiver::GetOwnPropertyAttribute(object, name);
} else {
*attributes = JSReceiver::GetPropertyAttribute(object, name);
}
diff --git a/src/cpu-profiler-inl.h b/src/cpu-profiler-inl.h
index c4efef1..e088f2e 100644
--- a/src/cpu-profiler-inl.h
+++ b/src/cpu-profiler-inl.h
@@ -28,6 +28,14 @@
}
+void CodeDisableOptEventRecord::UpdateCodeMap(CodeMap* code_map) {
+ CodeEntry* entry = code_map->FindEntry(start);
+ if (entry != NULL) {
+ entry->set_bailout_reason(bailout_reason);
+ }
+}
+
+
void SharedFunctionInfoMoveEventRecord::UpdateCodeMap(CodeMap* code_map) {
code_map->MoveCode(from, to);
}
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index abe2934..3a7c960 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -304,6 +304,15 @@
}
+void CpuProfiler::CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) {
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_DISABLE_OPT);
+ CodeDisableOptEventRecord* rec = &evt_rec.CodeDisableOptEventRecord_;
+ rec->start = code->address();
+ rec->bailout_reason = GetBailoutReason(shared->DisableOptimizationReason());
+ processor_->Enqueue(evt_rec);
+}
+
+
void CpuProfiler::CodeDeleteEvent(Address from) {
}
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
index e87fe9e..b9f9f98 100644
--- a/src/cpu-profiler.h
+++ b/src/cpu-profiler.h
@@ -26,6 +26,7 @@
#define CODE_EVENTS_TYPE_LIST(V) \
V(CODE_CREATION, CodeCreateEventRecord) \
V(CODE_MOVE, CodeMoveEventRecord) \
+ V(CODE_DISABLE_OPT, CodeDisableOptEventRecord) \
V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord) \
V(REPORT_BUILTIN, ReportBuiltinEventRecord)
@@ -65,6 +66,15 @@
};
+class CodeDisableOptEventRecord : public CodeEventRecord {
+ public:
+ Address start;
+ const char* bailout_reason;
+
+ INLINE(void UpdateCodeMap(CodeMap* code_map));
+};
+
+
class SharedFunctionInfoMoveEventRecord : public CodeEventRecord {
public:
Address from;
@@ -225,6 +235,7 @@
Code* code, int args_count);
virtual void CodeMovingGCEvent() {}
virtual void CodeMoveEvent(Address from, Address to);
+ virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared);
virtual void CodeDeleteEvent(Address from);
virtual void GetterCallbackEvent(Name* name, Address entry_point);
virtual void RegExpCodeCreateEvent(Code* code, String* source);
diff --git a/src/d8-readline.cc b/src/d8-readline.cc
index 225c6f0..a11cf4d 100644
--- a/src/d8-readline.cc
+++ b/src/d8-readline.cc
@@ -82,10 +82,7 @@
Handle<String> ReadLineEditor::Prompt(const char* prompt) {
char* result = NULL;
- { // Release lock for blocking input.
- Unlocker unlock(isolate_);
- result = readline(prompt);
- }
+ result = readline(prompt);
if (result == NULL) return Handle<String>();
AddHistory(result);
return String::NewFromUtf8(isolate_, result);
@@ -123,7 +120,6 @@
static unsigned current_index;
static Persistent<Array> current_completions;
Isolate* isolate = read_line_editor.isolate_;
- Locker lock(isolate);
HandleScope scope(isolate);
Handle<Array> completions;
if (state == 0) {
diff --git a/src/d8.cc b/src/d8.cc
index a467333..ffc58e6 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -472,10 +472,7 @@
// not been fully read into the buffer yet (does not end with '\n').
// If fgets gets an error, just give up.
char* input = NULL;
- { // Release lock for blocking input.
- Unlocker unlock(isolate);
- input = fgets(buffer, kBufferSize, stdin);
- }
+ input = fgets(buffer, kBufferSize, stdin);
if (input == NULL) return Handle<String>();
length = static_cast<int>(strlen(buffer));
if (length == 0) {
@@ -737,7 +734,6 @@
void Shell::InstallUtilityScript(Isolate* isolate) {
- Locker lock(isolate);
HandleScope scope(isolate);
// If we use the utility context, we have to set the security tokens so that
// utility, evaluation and debug context can all access each other.
@@ -904,7 +900,6 @@
void Shell::InitializeDebugger(Isolate* isolate) {
if (options.test_shell) return;
#ifndef V8_SHARED
- Locker lock(isolate);
HandleScope scope(isolate);
Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
utility_context_.Reset(isolate,
@@ -1031,8 +1026,6 @@
static char* ReadChars(Isolate* isolate, const char* name, int* size_out) {
- // Release the V8 lock while reading files.
- v8::Unlocker unlocker(isolate);
FILE* file = FOpen(name, "rb");
if (file == NULL) return NULL;
@@ -1112,7 +1105,6 @@
void Shell::RunShell(Isolate* isolate) {
- Locker locker(isolate);
HandleScope outer_scope(isolate);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate, evaluation_context_);
@@ -1204,7 +1196,6 @@
next_semaphore_.Wait();
{
Isolate::Scope iscope(isolate);
- Locker lock(isolate);
{
HandleScope scope(isolate);
PerIsolateData data(isolate);
@@ -1351,34 +1342,31 @@
options.isolate_sources[i].StartExecuteInThread();
}
#endif // !V8_SHARED
- { // NOLINT
- Locker lock(isolate);
- {
- HandleScope scope(isolate);
- Local<Context> context = CreateEvaluationContext(isolate);
- if (options.last_run) {
- // Keep using the same context in the interactive shell.
- evaluation_context_.Reset(isolate, context);
+ {
+ HandleScope scope(isolate);
+ Local<Context> context = CreateEvaluationContext(isolate);
+ if (options.last_run) {
+ // Keep using the same context in the interactive shell.
+ evaluation_context_.Reset(isolate, context);
#ifndef V8_SHARED
- // If the interactive debugger is enabled make sure to activate
- // it before running the files passed on the command line.
- if (i::FLAG_debugger) {
- InstallUtilityScript(isolate);
- }
+ // If the interactive debugger is enabled make sure to activate
+ // it before running the files passed on the command line.
+ if (i::FLAG_debugger) {
+ InstallUtilityScript(isolate);
+ }
#endif // !V8_SHARED
- }
- {
- Context::Scope cscope(context);
- PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
- options.isolate_sources[0].Execute(isolate);
- }
}
- if (!options.last_run) {
- if (options.send_idle_notification) {
- const int kLongIdlePauseInMs = 1000;
- V8::ContextDisposedNotification();
- V8::IdleNotification(kLongIdlePauseInMs);
- }
+ {
+ Context::Scope cscope(context);
+ PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
+ options.isolate_sources[0].Execute(isolate);
+ }
+ }
+ if (!options.last_run) {
+ if (options.send_idle_notification) {
+ const int kLongIdlePauseInMs = 1000;
+ V8::ContextDisposedNotification();
+ V8::IdleNotification(kLongIdlePauseInMs);
}
}
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index ebd7dbd..660ea79 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -2485,17 +2485,6 @@
};
-function NumberToHex8Str(n) {
- var r = "";
- for (var i = 0; i < 8; ++i) {
- var c = hexCharArray[n & 0x0F]; // hexCharArray is defined in uri.js
- r = c + r;
- n = n >>> 4;
- }
- return r;
-}
-
-
/**
* Convert an Object to its debugger protocol representation. The representation
* may be serilized to a JSON object using JSON.stringify().
diff --git a/src/debug.cc b/src/debug.cc
index 6cfc500..8956e92 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -2053,6 +2053,7 @@
Heap* heap = isolate_->heap();
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
"preparing for breakpoints");
+ HeapIterator iterator(heap);
// Ensure no GC in this scope as we are going to use gc_metadata
// field in the Code object to mark active functions.
@@ -2072,7 +2073,6 @@
// Scan the heap for all non-optimized functions which have no
// debug break slots and are not active or inlined into an active
// function and mark them for lazy compilation.
- HeapIterator iterator(heap);
HeapObject* obj = NULL;
while (((obj = iterator.next()) != NULL)) {
if (obj->IsJSFunction()) {
@@ -2197,9 +2197,7 @@
Handle<SharedFunctionInfo> target;
Heap* heap = isolate_->heap();
while (!done) {
- { // Extra scope for iterator and no-allocation.
- heap->EnsureHeapIsIterable();
- DisallowHeapAllocation no_alloc_during_heap_iteration;
+ { // Extra scope for iterator.
HeapIterator iterator(heap);
for (HeapObject* obj = iterator.next();
obj != NULL; obj = iterator.next()) {
@@ -2529,8 +2527,6 @@
// scripts which are no longer referenced. The second also sweeps precisely,
// which saves us doing yet another GC to make the heap iterable.
heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache");
- heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
- "Debug::CreateScriptCache");
ASSERT(script_cache_ == NULL);
script_cache_ = new ScriptCache(isolate_);
@@ -2538,7 +2534,6 @@
// Scan heap for Script objects.
int count = 0;
HeapIterator iterator(heap);
- DisallowHeapAllocation no_allocation;
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
diff --git a/src/debug.h b/src/debug.h
index 7956237..e0f3ea0 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -342,12 +342,13 @@
};
// Support for setting the address to jump to when returning from break point.
- Address* after_break_target_address() {
- return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
+ Address after_break_target_address() {
+ return reinterpret_cast<Address>(&thread_local_.after_break_target_);
}
- Address* restarter_frame_function_pointer_address() {
+
+ Address restarter_frame_function_pointer_address() {
Object*** address = &thread_local_.restarter_frame_function_pointer_;
- return reinterpret_cast<Address*>(address);
+ return reinterpret_cast<Address>(address);
}
static const int kEstimatedNofDebugInfoEntries = 16;
@@ -927,39 +928,6 @@
bool prev_disable_break_;
};
-
-// Debug_Address encapsulates the Address pointers used in generating debug
-// code.
-class Debug_Address {
- public:
- explicit Debug_Address(Debug::AddressId id) : id_(id) { }
-
- static Debug_Address AfterBreakTarget() {
- return Debug_Address(Debug::k_after_break_target_address);
- }
-
- static Debug_Address RestarterFrameFunctionPointer() {
- return Debug_Address(Debug::k_restarter_frame_function_pointer);
- }
-
- Address address(Isolate* isolate) const {
- Debug* debug = isolate->debug();
- switch (id_) {
- case Debug::k_after_break_target_address:
- return reinterpret_cast<Address>(debug->after_break_target_address());
- case Debug::k_restarter_frame_function_pointer:
- return reinterpret_cast<Address>(
- debug->restarter_frame_function_pointer_address());
- default:
- UNREACHABLE();
- return NULL;
- }
- }
-
- private:
- Debug::AddressId id_;
-};
-
} } // namespace v8::internal
#endif // V8_DEBUG_H_
diff --git a/src/elements-kind.cc b/src/elements-kind.cc
index adab396..d585eaa 100644
--- a/src/elements-kind.cc
+++ b/src/elements-kind.cc
@@ -51,6 +51,12 @@
}
+int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
+ return IsExternalArrayElementsKind(elements_kind)
+ ? 0 : (FixedArray::kHeaderSize - kSmiTagSize);
+}
+
+
const char* ElementsKindToString(ElementsKind kind) {
ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
return accessor->name();
diff --git a/src/elements-kind.h b/src/elements-kind.h
index 1a550b0..28f4429 100644
--- a/src/elements-kind.h
+++ b/src/elements-kind.h
@@ -72,6 +72,7 @@
FAST_HOLEY_SMI_ELEMENTS - FAST_SMI_ELEMENTS;
int ElementsKindToShiftSize(ElementsKind elements_kind);
+int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind);
const char* ElementsKindToString(ElementsKind kind);
void PrintElementsKind(FILE* out, ElementsKind kind);
diff --git a/src/factory.cc b/src/factory.cc
index f99ea9b..4300b24 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -1294,10 +1294,10 @@
Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
if (!function->shared()->is_generator()) {
- JSObject::SetLocalPropertyIgnoreAttributes(prototype,
- constructor_string(),
- function,
- DONT_ENUM).Assert();
+ JSObject::SetOwnPropertyIgnoreAttributes(prototype,
+ constructor_string(),
+ function,
+ DONT_ENUM).Assert();
}
return prototype;
@@ -1990,7 +1990,7 @@
// cache in the snapshot to keep boot-time memory usage down.
// If we expand the number string cache already while creating
// the snapshot then that didn't work out.
- ASSERT(!Serializer::enabled(isolate()) || FLAG_extra_code != NULL);
+ ASSERT(!isolate()->serializer_enabled() || FLAG_extra_code != NULL);
Handle<FixedArray> new_cache = NewFixedArray(full_size, TENURED);
isolate()->heap()->set_number_string_cache(*new_cache);
return;
@@ -2131,7 +2131,7 @@
return result;
}
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
handle(JSObject::cast(result->prototype())),
constructor_string(),
result,
diff --git a/src/frames.cc b/src/frames.cc
index e7c2a14..73234e00 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -640,7 +640,7 @@
// Skip saved double registers.
if (safepoint_entry.has_doubles()) {
// Number of doubles not known at snapshot time.
- ASSERT(!Serializer::enabled(isolate()));
+ ASSERT(!isolate()->serializer_enabled());
parameters_base += DoubleRegister::NumAllocatableRegisters() *
kDoubleSize / kPointerSize;
}
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index 6068bf4..4b7443a 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -173,9 +173,6 @@
Handle<HeapObject> HeapProfiler::FindHeapObjectById(SnapshotObjectId id) {
- heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
- "HeapProfiler::FindHeapObjectById");
- DisallowHeapAllocation no_allocation;
HeapObject* object = NULL;
HeapIterator iterator(heap(), HeapIterator::kFilterUnreachable);
// Make sure that object with the given id is still reachable.
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index cafee77..fb1fa38 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -155,6 +155,7 @@
case kSynthetic: return "/synthetic/";
case kConsString: return "/concatenated string/";
case kSlicedString: return "/sliced string/";
+ case kSymbol: return "/symbol/";
default: return "???";
}
}
@@ -851,6 +852,8 @@
return AddEntry(object,
HeapEntry::kString,
names_->GetName(String::cast(object)));
+ } else if (object->IsSymbol()) {
+ return AddEntry(object, HeapEntry::kSymbol, "symbol");
} else if (object->IsCode()) {
return AddEntry(object, HeapEntry::kCode, "");
} else if (object->IsSharedFunctionInfo()) {
@@ -1098,6 +1101,8 @@
ExtractJSObjectReferences(entry, JSObject::cast(obj));
} else if (obj->IsString()) {
ExtractStringReferences(entry, String::cast(obj));
+ } else if (obj->IsSymbol()) {
+ ExtractSymbolReferences(entry, Symbol::cast(obj));
} else if (obj->IsMap()) {
ExtractMapReferences(entry, Map::cast(obj));
} else if (obj->IsSharedFunctionInfo()) {
@@ -1244,6 +1249,13 @@
}
+void V8HeapExplorer::ExtractSymbolReferences(int entry, Symbol* symbol) {
+ SetInternalReference(symbol, entry,
+ "name", symbol->name(),
+ Symbol::kNameOffset);
+}
+
+
void V8HeapExplorer::ExtractContextReferences(int entry, Context* context) {
if (context == context->declaration_context()) {
ScopeInfo* scope_info = context->closure()->shared()->scope_info();
@@ -1752,7 +1764,7 @@
Object* constructor_prop = NULL;
Isolate* isolate = heap->isolate();
LookupResult result(isolate);
- object->LocalLookupRealNamedProperty(
+ object->LookupOwnRealNamedProperty(
isolate->factory()->constructor_string(), &result);
if (!result.IsFound()) return object->constructor_name();
@@ -2569,10 +2581,6 @@
CHECK(!debug_heap->map_space()->was_swept_conservatively());
#endif
- // The following code uses heap iterators, so we want the heap to be
- // stable. It should follow TagGlobalObjects as that can allocate.
- DisallowHeapAllocation no_alloc;
-
#ifdef VERIFY_HEAP
debug_heap->Verify();
#endif
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index a0f2a62..e1c291e 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -83,7 +83,8 @@
kNative = v8::HeapGraphNode::kNative,
kSynthetic = v8::HeapGraphNode::kSynthetic,
kConsString = v8::HeapGraphNode::kConsString,
- kSlicedString = v8::HeapGraphNode::kSlicedString
+ kSlicedString = v8::HeapGraphNode::kSlicedString,
+ kSymbol = v8::HeapGraphNode::kSymbol
};
static const int kNoEntry;
@@ -368,6 +369,7 @@
void ExtractJSGlobalProxyReferences(int entry, JSGlobalProxy* proxy);
void ExtractJSObjectReferences(int entry, JSObject* js_obj);
void ExtractStringReferences(int entry, String* obj);
+ void ExtractSymbolReferences(int entry, Symbol* symbol);
void ExtractContextReferences(int entry, Context* context);
void ExtractMapReferences(int entry, Map* map);
void ExtractSharedFunctionInfoReferences(int entry,
diff --git a/src/heap.cc b/src/heap.cc
index b672bbf..66d17fb 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -699,6 +699,10 @@
ReportStatisticsAfterGC();
#endif // DEBUG
isolate_->debug()->AfterGarbageCollection();
+
+ // Remember the last top pointer so that we can later find out
+ // whether we allocated in new space since the last GC.
+ new_space_top_after_last_gc_ = new_space()->top();
}
@@ -4321,14 +4325,15 @@
bool Heap::IsHeapIterable() {
return (!old_pointer_space()->was_swept_conservatively() &&
- !old_data_space()->was_swept_conservatively());
+ !old_data_space()->was_swept_conservatively() &&
+ new_space_top_after_last_gc_ == new_space()->top());
}
-void Heap::EnsureHeapIsIterable() {
+void Heap::MakeHeapIterable() {
ASSERT(AllowHeapAllocation::IsAllowed());
if (!IsHeapIterable()) {
- CollectAllGarbage(kMakeHeapIterableMask, "Heap::EnsureHeapIsIterable");
+ CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable");
}
ASSERT(IsHeapIterable());
}
@@ -4389,7 +4394,7 @@
return false;
}
- if (!FLAG_incremental_marking || Serializer::enabled(isolate_)) {
+ if (!FLAG_incremental_marking || isolate_->serializer_enabled()) {
return IdleGlobalGC();
}
@@ -5052,9 +5057,8 @@
initial_semispace_size_ = Min(initial_semispace_size_, max_semi_space_size_);
// The external allocation limit should be below 256 MB on all architectures
- // to avoid unnecessary low memory notifications, as that is the threshold
- // for some embedders.
- external_allocation_limit_ = 12 * max_semi_space_size_;
+ // to avoid that resource-constrained embedders run low on memory.
+ external_allocation_limit_ = 192 * MB;
ASSERT(external_allocation_limit_ <= 256 * MB);
// The old generation is paged and needs at least one page for each space.
@@ -5209,6 +5213,7 @@
if (!new_space_.SetUp(reserved_semispace_size_, max_semi_space_size_)) {
return false;
}
+ new_space_top_after_last_gc_ = new_space()->top();
// Initialize old pointer space.
old_pointer_space_ =
@@ -5732,7 +5737,9 @@
HeapIterator::HeapIterator(Heap* heap)
- : heap_(heap),
+ : make_heap_iterable_helper_(heap),
+ no_heap_allocation_(),
+ heap_(heap),
filtering_(HeapIterator::kNoFiltering),
filter_(NULL) {
Init();
@@ -5741,7 +5748,9 @@
HeapIterator::HeapIterator(Heap* heap,
HeapIterator::HeapObjectsFiltering filtering)
- : heap_(heap),
+ : make_heap_iterable_helper_(heap),
+ no_heap_allocation_(),
+ heap_(heap),
filtering_(filtering),
filter_(NULL) {
Init();
diff --git a/src/heap.h b/src/heap.h
index 9ccbe66..08e0fcc 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -767,7 +767,7 @@
// Ensure that we have swept all spaces in such a way that we can iterate
// over all objects. May cause a GC.
- void EnsureHeapIsIterable();
+ void MakeHeapIterable();
// Notify the heap that a context has been disposed.
int NotifyContextDisposed();
@@ -1549,6 +1549,7 @@
LargeObjectSpace* lo_space_;
HeapState gc_state_;
int gc_post_processing_depth_;
+ Address new_space_top_after_last_gc_;
// Returns the amount of external memory registered since last global gc.
int64_t PromotedExternalMemorySize();
@@ -2391,6 +2392,9 @@
// aggregates the specific iterators for the different spaces as
// these can only iterate over one space only.
//
+// HeapIterator ensures there is no allocation during its lifetime
+// (using an embedded DisallowHeapAllocation instance).
+//
// HeapIterator can skip free list nodes (that is, de-allocated heap
// objects that still remain in the heap). As implementation of free
// nodes filtering uses GC marks, it can't be used during MS/MC GC
@@ -2413,12 +2417,18 @@
void reset();
private:
+ struct MakeHeapIterableHelper {
+ explicit MakeHeapIterableHelper(Heap* heap) { heap->MakeHeapIterable(); }
+ };
+
// Perform the initialization.
void Init();
// Perform all necessary shutdown (destruction) work.
void Shutdown();
HeapObject* NextObject();
+ MakeHeapIterableHelper make_heap_iterable_helper_;
+ DisallowHeapAllocation no_heap_allocation_;
Heap* heap_;
HeapObjectsFiltering filtering_;
HeapObjectsFilter* filter_;
diff --git a/src/hydrogen-dehoist.cc b/src/hydrogen-dehoist.cc
index 44aeb48..e800823 100644
--- a/src/hydrogen-dehoist.cc
+++ b/src/hydrogen-dehoist.cc
@@ -30,12 +30,13 @@
int32_t value = constant->Integer32Value() * sign;
// We limit offset values to 30 bits because we want to avoid the risk of
// overflows when the offset is added to the object header size.
- if (value >= 1 << array_operation->MaxIndexOffsetBits() || value < 0) return;
+ if (value >= 1 << array_operation->MaxBaseOffsetBits() || value < 0) return;
array_operation->SetKey(subexpression);
if (binary_operation->HasNoUses()) {
binary_operation->DeleteAndReplaceWith(NULL);
}
- array_operation->SetIndexOffset(static_cast<uint32_t>(value));
+ value <<= ElementsKindToShiftSize(array_operation->elements_kind());
+ array_operation->IncreaseBaseOffset(static_cast<uint32_t>(value));
array_operation->SetDehoisted(true);
}
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index bfdc949..9bd0464 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -3457,7 +3457,7 @@
stream->Add("[");
key()->PrintNameTo(stream);
if (IsDehoisted()) {
- stream->Add(" + %d]", index_offset());
+ stream->Add(" + %d]", base_offset());
} else {
stream->Add("]");
}
@@ -3609,7 +3609,7 @@
stream->Add("[");
key()->PrintNameTo(stream);
if (IsDehoisted()) {
- stream->Add(" + %d] = ", index_offset());
+ stream->Add(" + %d] = ", base_offset());
} else {
stream->Add("] = ");
}
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index cf3497f..05b3116 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -1079,6 +1079,18 @@
return new(zone) I(p1, p2, p3, p4, p5); \
}
+#define DECLARE_INSTRUCTION_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
+ static I* New(Zone* zone, \
+ HValue* context, \
+ P1 p1, \
+ P2 p2, \
+ P3 p3, \
+ P4 p4, \
+ P5 p5, \
+ P6 p6) { \
+ return new(zone) I(p1, p2, p3, p4, p5, p6); \
+ }
+
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
static I* New(Zone* zone, HValue* context) { \
return new(zone) I(context); \
@@ -6413,8 +6425,9 @@
public:
virtual HValue* GetKey() = 0;
virtual void SetKey(HValue* key) = 0;
- virtual void SetIndexOffset(uint32_t index_offset) = 0;
- virtual int MaxIndexOffsetBits() = 0;
+ virtual ElementsKind elements_kind() const = 0;
+ virtual void IncreaseBaseOffset(uint32_t base_offset) = 0;
+ virtual int MaxBaseOffsetBits() = 0;
virtual bool IsDehoisted() = 0;
virtual void SetDehoisted(bool is_dehoisted) = 0;
virtual ~ArrayInstructionInterface() { }
@@ -6426,6 +6439,8 @@
};
+static const int kDefaultKeyedHeaderOffsetSentinel = -1;
+
enum LoadKeyedHoleMode {
NEVER_RETURN_HOLE,
ALLOW_RETURN_HOLE
@@ -6439,6 +6454,8 @@
ElementsKind);
DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
ElementsKind, LoadKeyedHoleMode);
+ DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*,
+ ElementsKind, LoadKeyedHoleMode, int);
bool is_external() const {
return IsExternalArrayElementsKind(elements_kind());
@@ -6456,12 +6473,13 @@
return OperandAt(2);
}
bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
- uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); }
- void SetIndexOffset(uint32_t index_offset) {
- bit_field_ = IndexOffsetField::update(bit_field_, index_offset);
+ uint32_t base_offset() { return BaseOffsetField::decode(bit_field_); }
+ void IncreaseBaseOffset(uint32_t base_offset) {
+ base_offset += BaseOffsetField::decode(bit_field_);
+ bit_field_ = BaseOffsetField::update(bit_field_, base_offset);
}
- virtual int MaxIndexOffsetBits() {
- return kBitsForIndexOffset;
+ virtual int MaxBaseOffsetBits() {
+ return kBitsForBaseOffset;
}
HValue* GetKey() { return key(); }
void SetKey(HValue* key) { SetOperandAt(1, key); }
@@ -6511,7 +6529,7 @@
if (!other->IsLoadKeyed()) return false;
HLoadKeyed* other_load = HLoadKeyed::cast(other);
- if (IsDehoisted() && index_offset() != other_load->index_offset())
+ if (IsDehoisted() && base_offset() != other_load->base_offset())
return false;
return elements_kind() == other_load->elements_kind();
}
@@ -6521,10 +6539,15 @@
HValue* key,
HValue* dependency,
ElementsKind elements_kind,
- LoadKeyedHoleMode mode = NEVER_RETURN_HOLE)
+ LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
+ int offset = kDefaultKeyedHeaderOffsetSentinel)
: bit_field_(0) {
+ offset = offset == kDefaultKeyedHeaderOffsetSentinel
+ ? GetDefaultHeaderSizeForElementsKind(elements_kind)
+ : offset;
bit_field_ = ElementsKindField::encode(elements_kind) |
- HoleModeField::encode(mode);
+ HoleModeField::encode(mode) |
+ BaseOffsetField::encode(offset);
SetOperandAt(0, obj);
SetOperandAt(1, key);
@@ -6587,16 +6610,16 @@
enum LoadKeyedBits {
kBitsForElementsKind = 5,
kBitsForHoleMode = 1,
- kBitsForIndexOffset = 25,
+ kBitsForBaseOffset = 25,
kBitsForIsDehoisted = 1,
kStartElementsKind = 0,
kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
- kStartIndexOffset = kStartHoleMode + kBitsForHoleMode,
- kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset
+ kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
+ kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
};
- STATIC_ASSERT((kBitsForElementsKind + kBitsForIndexOffset +
+ STATIC_ASSERT((kBitsForElementsKind + kBitsForBaseOffset +
kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
class ElementsKindField:
@@ -6605,8 +6628,8 @@
class HoleModeField:
public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
{}; // NOLINT
- class IndexOffsetField:
- public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset>
+ class BaseOffsetField:
+ public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
{}; // NOLINT
class IsDehoistedField:
public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
@@ -6726,6 +6749,7 @@
ASSERT(!has_transition()); // Only set once.
SetOperandAt(2, transition);
has_transition_ = true;
+ SetChangesFlag(kMaps);
}
bool NeedsWriteBarrier() {
@@ -6752,6 +6776,19 @@
SetOperandAt(1, value);
}
+ bool CanBeReplacedWith(HStoreNamedField* that) const {
+ if (!this->access().Equals(that->access())) return false;
+ if (SmiValuesAre32Bits() &&
+ this->field_representation().IsSmi() &&
+ this->store_mode() == INITIALIZING_STORE &&
+ that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
+ // We cannot replace an initializing store to a smi field with a store to
+ // an initialized entry on 64-bit architectures (with 32-bit smis).
+ return false;
+ }
+ return true;
+ }
+
private:
HStoreNamedField(HValue* obj,
HObjectAccess access,
@@ -6823,6 +6860,8 @@
ElementsKind);
DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
ElementsKind, StoreFieldOrKeyedMode);
+ DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
+ ElementsKind, StoreFieldOrKeyedMode, int);
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
// kind_fast: tagged[int32] = tagged
@@ -6895,9 +6934,11 @@
}
StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
ElementsKind elements_kind() const { return elements_kind_; }
- uint32_t index_offset() { return index_offset_; }
- void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
- virtual int MaxIndexOffsetBits() {
+ uint32_t base_offset() { return base_offset_; }
+ void IncreaseBaseOffset(uint32_t base_offset) {
+ base_offset_ += base_offset;
+ }
+ virtual int MaxBaseOffsetBits() {
return 31 - ElementsKindToShiftSize(elements_kind_);
}
HValue* GetKey() { return key(); }
@@ -6941,9 +6982,12 @@
private:
HStoreKeyed(HValue* obj, HValue* key, HValue* val,
ElementsKind elements_kind,
- StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
+ StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
+ int offset = kDefaultKeyedHeaderOffsetSentinel)
: elements_kind_(elements_kind),
- index_offset_(0),
+ base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
+ ? GetDefaultHeaderSizeForElementsKind(elements_kind)
+ : offset),
is_dehoisted_(false),
is_uninitialized_(false),
store_mode_(store_mode),
@@ -6983,7 +7027,7 @@
}
ElementsKind elements_kind_;
- uint32_t index_offset_;
+ uint32_t base_offset_;
bool is_dehoisted_ : 1;
bool is_uninitialized_ : 1;
StoreFieldOrKeyedMode store_mode_: 1;
diff --git a/src/hydrogen-store-elimination.cc b/src/hydrogen-store-elimination.cc
index cf5f3a1..bbb115a 100644
--- a/src/hydrogen-store-elimination.cc
+++ b/src/hydrogen-store-elimination.cc
@@ -58,7 +58,7 @@
while (i < unobserved_.length()) {
HStoreNamedField* prev = unobserved_.at(i);
if (aliasing_->MustAlias(object, prev->object()->ActualValue()) &&
- store->access().Equals(prev->access())) {
+ prev->CanBeReplacedWith(store)) {
// This store is guaranteed to overwrite the previous store.
prev->DeleteAndReplaceWith(NULL);
TRACE(("++ Unobserved store S%d overwritten by S%d\n",
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index b296b93..5d78a4a 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -2473,14 +2473,14 @@
}
// Special loop unfolding case
- static const int kLoopUnfoldLimit = 8;
- STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit);
+ STATIC_ASSERT(JSArray::kPreallocatedArrayElements <=
+ kElementLoopUnrollThreshold);
int initial_capacity = -1;
if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
int constant_from = from->GetInteger32Constant();
int constant_to = to->GetInteger32Constant();
- if (constant_from == 0 && constant_to <= kLoopUnfoldLimit) {
+ if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
initial_capacity = constant_to;
}
}
@@ -7880,6 +7880,7 @@
ElementsKind elements_kind = receiver_map->elements_kind();
if (!IsFastElementsKind(elements_kind)) return false;
if (receiver_map->is_observed()) return false;
+ if (JSArray::IsReadOnlyLengthDescriptor(receiver_map)) return false;
ASSERT(receiver_map->is_extensible());
// If there may be elements accessors in the prototype chain, the fast
@@ -8033,7 +8034,7 @@
if (call_type == kCallApiFunction) {
// Cannot embed a direct reference to the global proxy map
// as it maybe dropped on deserialization.
- CHECK(!Serializer::enabled(isolate()));
+ CHECK(!isolate()->serializer_enabled());
ASSERT_EQ(0, receiver_maps->length());
receiver_maps->Add(handle(
function->context()->global_object()->global_receiver()->map()),
@@ -8220,7 +8221,7 @@
if (shared->strict_mode() == SLOPPY && !shared->native()) {
// Cannot embed a direct reference to the global proxy
// as is it dropped on deserialization.
- CHECK(!Serializer::enabled(isolate()));
+ CHECK(!isolate()->serializer_enabled());
Handle<JSObject> global_receiver(
target->context()->global_object()->global_receiver());
return Add<HConstant>(global_receiver);
@@ -8229,6 +8230,56 @@
}
+void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
+ int arguments_count,
+ HValue* function,
+ Handle<AllocationSite> site) {
+ Add<HCheckValue>(function, array_function());
+
+ if (IsCallArrayInlineable(arguments_count, site)) {
+ BuildInlinedCallArray(expression, arguments_count, site);
+ return;
+ }
+
+ HInstruction* call = PreProcessCall(New<HCallNewArray>(
+ function, arguments_count + 1, site->GetElementsKind()));
+ if (expression->IsCall()) {
+ Drop(1);
+ }
+ ast_context()->ReturnInstruction(call, expression->id());
+}
+
+
+bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
+ if (!array_function().is_identical_to(expr->target())) {
+ return false;
+ }
+
+ Handle<AllocationSite> site = expr->allocation_site();
+ if (site.is_null()) return false;
+
+ BuildArrayCall(expr,
+ expr->arguments()->length(),
+ function,
+ site);
+ return true;
+}
+
+
+bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
+ HValue* function) {
+ if (!array_function().is_identical_to(expr->target())) {
+ return false;
+ }
+
+ BuildArrayCall(expr,
+ expr->arguments()->length(),
+ function,
+ expr->allocation_site());
+ return true;
+}
+
+
void HOptimizedGraphBuilder::VisitCall(Call* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
@@ -8323,8 +8374,7 @@
// evaluation of the arguments.
CHECK_ALIVE(VisitForValue(expr->expression()));
HValue* function = Top();
- bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
- if (global_call) {
+ if (expr->global_call()) {
Variable* var = proxy->var();
bool known_global_function = false;
// If there is a global property cell for the name at compile time and
@@ -8358,6 +8408,7 @@
return;
}
if (TryInlineApiFunctionCall(expr, receiver)) return;
+ if (TryHandleArrayCall(expr, function)) return;
if (TryInlineCall(expr)) return;
PushArgumentsFromEnvironment(argument_count);
@@ -8407,20 +8458,21 @@
}
-void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) {
+void HOptimizedGraphBuilder::BuildInlinedCallArray(
+ Expression* expression,
+ int argument_count,
+ Handle<AllocationSite> site) {
+ ASSERT(!site.is_null());
+ ASSERT(argument_count >= 0 && argument_count <= 1);
NoObservableSideEffectsScope no_effects(this);
- int argument_count = expr->arguments()->length();
// We should at least have the constructor on the expression stack.
HValue* constructor = environment()->ExpressionStackAt(argument_count);
- ElementsKind kind = expr->elements_kind();
- Handle<AllocationSite> site = expr->allocation_site();
- ASSERT(!site.is_null());
-
// Register on the site for deoptimization if the transition feedback changes.
AllocationSite::AddDependentCompilationInfo(
site, AllocationSite::TRANSITIONS, top_info());
+ ElementsKind kind = site->GetElementsKind();
HInstruction* site_instruction = Add<HConstant>(site);
// In the single constant argument case, we may have to adjust elements kind
@@ -8443,32 +8495,12 @@
site_instruction,
constructor,
DISABLE_ALLOCATION_SITES);
- HValue* new_object;
- if (argument_count == 0) {
- new_object = array_builder.AllocateEmptyArray();
- } else if (argument_count == 1) {
- HValue* argument = environment()->Top();
- new_object = BuildAllocateArrayFromLength(&array_builder, argument);
- } else {
- HValue* length = Add<HConstant>(argument_count);
- // Smi arrays need to initialize array elements with the hole because
- // bailout could occur if the arguments don't fit in a smi.
- //
- // TODO(mvstanton): If all the arguments are constants in smi range, then
- // we could set fill_with_hole to false and save a few instructions.
- JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind)
- ? JSArrayBuilder::FILL_WITH_HOLE
- : JSArrayBuilder::DONT_FILL_WITH_HOLE;
- new_object = array_builder.AllocateArray(length, length, fill_mode);
- HValue* elements = array_builder.GetElementsLocation();
- for (int i = 0; i < argument_count; i++) {
- HValue* value = environment()->ExpressionStackAt(argument_count - i - 1);
- HValue* constant_i = Add<HConstant>(i);
- Add<HStoreKeyed>(elements, constant_i, value, kind);
- }
- }
+ HValue* new_object = argument_count == 0
+ ? array_builder.AllocateEmptyArray()
+ : BuildAllocateArrayFromLength(&array_builder, Top());
- Drop(argument_count + 1); // drop constructor and args.
+ int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
+ Drop(args_to_drop);
ast_context()->ReturnValue(new_object);
}
@@ -8482,14 +8514,13 @@
}
-bool HOptimizedGraphBuilder::IsCallNewArrayInlineable(CallNew* expr) {
+bool HOptimizedGraphBuilder::IsCallArrayInlineable(
+ int argument_count,
+ Handle<AllocationSite> site) {
Handle<JSFunction> caller = current_info()->closure();
- Handle<JSFunction> target(isolate()->native_context()->array_function(),
- isolate());
- int argument_count = expr->arguments()->length();
+ Handle<JSFunction> target = array_function();
// We should have the function plus array arguments on the environment stack.
ASSERT(environment()->length() >= (argument_count + 1));
- Handle<AllocationSite> site = expr->allocation_site();
ASSERT(!site.is_null());
bool inline_ok = false;
@@ -8499,22 +8530,24 @@
HValue* argument = Top();
if (argument->IsConstant()) {
// Do not inline if the constant length argument is not a smi or
- // outside the valid range for a fast array.
+ // outside the valid range for unrolled loop initialization.
HConstant* constant_argument = HConstant::cast(argument);
if (constant_argument->HasSmiValue()) {
int value = constant_argument->Integer32Value();
- inline_ok = value >= 0 &&
- value < JSObject::kInitialMaxFastElementArray;
+ inline_ok = value >= 0 && value <= kElementLoopUnrollThreshold;
if (!inline_ok) {
TraceInline(target, caller,
- "Length outside of valid array range");
+ "Constant length outside of valid inlining range.");
}
}
} else {
- inline_ok = true;
+ TraceInline(target, caller,
+ "Dont inline [new] Array(n) where n isn't constant.");
}
- } else {
+ } else if (argument_count == 0) {
inline_ok = true;
+ } else {
+ TraceInline(target, caller, "Too many arguments to inline.");
}
} else {
TraceInline(target, caller, "AllocationSite requested no inlining.");
@@ -8644,25 +8677,10 @@
} else {
// The constructor function is both an operand to the instruction and an
// argument to the construct call.
- Handle<JSFunction> array_function(
- isolate()->native_context()->array_function(), isolate());
- bool use_call_new_array = expr->target().is_identical_to(array_function);
- if (use_call_new_array && IsCallNewArrayInlineable(expr)) {
- // Verify we are still calling the array function for our native context.
- Add<HCheckValue>(function, array_function);
- BuildInlinedCallNewArray(expr);
- return;
- }
+ if (TryHandleArrayCallNew(expr, function)) return;
- HBinaryCall* call;
- if (use_call_new_array) {
- Add<HCheckValue>(function, array_function);
- call = New<HCallNewArray>(function, argument_count,
- expr->elements_kind());
- } else {
- call = New<HCallNew>(function, argument_count);
- }
- PreProcessCall(call);
+ HInstruction* call =
+ PreProcessCall(New<HCallNew>(function, argument_count));
return ast_context()->ReturnInstruction(call, expr->id());
}
}
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 17cb7d1..bb05ebb 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -1295,6 +1295,10 @@
void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
+ // When initializing arrays, we'll unfold the loop if the number of elements
+ // is known at compile time and is <= kElementLoopUnrollThreshold.
+ static const int kElementLoopUnrollThreshold = 8;
+
protected:
virtual bool BuildGraph() = 0;
@@ -2242,6 +2246,11 @@
// Try to optimize fun.apply(receiver, arguments) pattern.
bool TryCallApply(Call* expr);
+ bool TryHandleArrayCall(Call* expr, HValue* function);
+ bool TryHandleArrayCallNew(CallNew* expr, HValue* function);
+ void BuildArrayCall(Expression* expr, int arguments_count, HValue* function,
+ Handle<AllocationSite> cell);
+
HValue* ImplicitReceiverFor(HValue* function,
Handle<JSFunction> target);
@@ -2325,8 +2334,13 @@
ElementsKind fixed_elements_kind,
HValue* byte_length, HValue* length);
- bool IsCallNewArrayInlineable(CallNew* expr);
- void BuildInlinedCallNewArray(CallNew* expr);
+ Handle<JSFunction> array_function() {
+ return handle(isolate()->native_context()->array_function());
+ }
+
+ bool IsCallArrayInlineable(int argument_count, Handle<AllocationSite> site);
+ void BuildInlinedCallArray(Expression* expression, int argument_count,
+ Handle<AllocationSite> site);
class PropertyAccessInfo {
public:
diff --git a/src/i18n.cc b/src/i18n.cc
index 2b6b0fb..9883ef2 100644
--- a/src/i18n.cc
+++ b/src/i18n.cc
@@ -435,7 +435,7 @@
Handle<String> key =
factory->NewStringFromStaticAscii("minimumSignificantDigits");
- if (JSReceiver::HasLocalProperty(resolved, key)) {
+ if (JSReceiver::HasOwnProperty(resolved, key)) {
JSObject::SetProperty(
resolved,
factory->NewStringFromStaticAscii("minimumSignificantDigits"),
@@ -445,7 +445,7 @@
}
key = factory->NewStringFromStaticAscii("maximumSignificantDigits");
- if (JSReceiver::HasLocalProperty(resolved, key)) {
+ if (JSReceiver::HasOwnProperty(resolved, key)) {
JSObject::SetProperty(
resolved,
factory->NewStringFromStaticAscii("maximumSignificantDigits"),
@@ -823,7 +823,7 @@
Handle<JSObject> obj) {
Handle<String> key =
isolate->factory()->NewStringFromStaticAscii("dateFormat");
- if (JSReceiver::HasLocalProperty(obj, key)) {
+ if (JSReceiver::HasOwnProperty(obj, key)) {
return reinterpret_cast<icu::SimpleDateFormat*>(
obj->GetInternalField(0));
}
@@ -897,7 +897,7 @@
Handle<JSObject> obj) {
Handle<String> key =
isolate->factory()->NewStringFromStaticAscii("numberFormat");
- if (JSReceiver::HasLocalProperty(obj, key)) {
+ if (JSReceiver::HasOwnProperty(obj, key)) {
return reinterpret_cast<icu::DecimalFormat*>(obj->GetInternalField(0));
}
@@ -952,7 +952,7 @@
icu::Collator* Collator::UnpackCollator(Isolate* isolate,
Handle<JSObject> obj) {
Handle<String> key = isolate->factory()->NewStringFromStaticAscii("collator");
- if (JSReceiver::HasLocalProperty(obj, key)) {
+ if (JSReceiver::HasOwnProperty(obj, key)) {
return reinterpret_cast<icu::Collator*>(obj->GetInternalField(0));
}
@@ -1011,7 +1011,7 @@
Handle<JSObject> obj) {
Handle<String> key =
isolate->factory()->NewStringFromStaticAscii("breakIterator");
- if (JSReceiver::HasLocalProperty(obj, key)) {
+ if (JSReceiver::HasOwnProperty(obj, key)) {
return reinterpret_cast<icu::BreakIterator*>(obj->GetInternalField(0));
}
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index fea67e3..cee926f 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -52,8 +52,6 @@
CPU cpu;
CHECK(cpu.has_sse2()); // SSE2 support is mandatory.
CHECK(cpu.has_cmov()); // CMOV support is mandatory.
- CHECK(cpu.has_sahf()); // SAHF must be available in compat/legacy mode.
- supported_ |= 1u << SAHF;
supported_ |= OS::CpuFeaturesImpliedByPlatform();
// Only use statically determined features for cross compile (snapshot).
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 8f9928e..5547ba2 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -2335,11 +2335,13 @@
}
-void CallFunctionStub::Generate(MacroAssembler* masm) {
+static void CallFunctionNoFeedback(MacroAssembler* masm,
+ int argc, bool needs_checks,
+ bool call_as_method) {
// edi : the function to call
Label slow, non_function, wrap, cont;
- if (NeedsChecks()) {
+ if (needs_checks) {
// Check that the function really is a JavaScript function.
__ JumpIfSmi(edi, &non_function);
@@ -2349,17 +2351,17 @@
}
// Fast-case: Just invoke the function.
- ParameterCount actual(argc_);
+ ParameterCount actual(argc);
- if (CallAsMethod()) {
- if (NeedsChecks()) {
+ if (call_as_method) {
+ if (needs_checks) {
EmitContinueIfStrictOrNative(masm, &cont);
}
// Load the receiver from the stack.
- __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize));
+ __ mov(eax, Operand(esp, (argc + 1) * kPointerSize));
- if (NeedsChecks()) {
+ if (call_as_method) {
__ JumpIfSmi(eax, &wrap);
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
@@ -2373,20 +2375,25 @@
__ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
- if (NeedsChecks()) {
+ if (needs_checks) {
// Slow-case: Non-function called.
__ bind(&slow);
// (non_function is bound in EmitSlowCase)
- EmitSlowCase(isolate(), masm, argc_, &non_function);
+ EmitSlowCase(masm->isolate(), masm, argc, &non_function);
}
- if (CallAsMethod()) {
+ if (call_as_method) {
__ bind(&wrap);
- EmitWrapCase(masm, argc_, &cont);
+ EmitWrapCase(masm, argc, &cont);
}
}
+void CallFunctionStub::Generate(MacroAssembler* masm) {
+ CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod());
+}
+
+
void CallConstructStub::Generate(MacroAssembler* masm) {
// eax : number of arguments
// ebx : feedback vector
@@ -2463,6 +2470,51 @@
}
+void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
+ // edi - function
+ // ebx - feedback vector
+ // edx - slot id
+ __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
+ __ cmp(edi, ecx);
+ __ j(not_equal, miss);
+
+ __ mov(eax, arg_count());
+ __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size,
+ FixedArray::kHeaderSize));
+ // Verify that ecx contains an AllocationSite
+ __ AssertUndefinedOrAllocationSite(ebx);
+ ArrayConstructorStub stub(masm->isolate(), arg_count());
+ __ TailCallStub(&stub);
+}
+
+
+void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) {
+ // edi - function
+ // ebx - feedback vector
+ // edx - slot id
+ Label miss;
+
+ if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) {
+ Generate_MonomorphicArray(masm, &miss);
+ } else {
+ // So far there is only one customer for our custom feedback scheme.
+ UNREACHABLE();
+ }
+
+ __ bind(&miss);
+ GenerateMiss(masm);
+
+ // The slow case, we need this no matter what to complete a call after a miss.
+ CallFunctionNoFeedback(masm,
+ arg_count(),
+ true,
+ CallAsMethod());
+
+ // Unreachable.
+ __ int3();
+}
+
+
void CallICStub::Generate(MacroAssembler* masm) {
// edi - function
// edx - slot id
@@ -2475,6 +2527,11 @@
EmitLoadTypeFeedbackVector(masm, ebx);
+ if (state_.stub_type() != CallIC::DEFAULT) {
+ Generate_CustomFeedbackCall(masm);
+ return;
+ }
+
// The checks. First, does edi match the recorded monomorphic target?
__ cmp(edi, FieldOperand(ebx, edx, times_half_pointer_size,
FixedArray::kHeaderSize));
diff --git a/src/ia32/debug-ia32.cc b/src/ia32/debug-ia32.cc
index e7a7b60..d9d970e 100644
--- a/src/ia32/debug-ia32.cc
+++ b/src/ia32/debug-ia32.cc
@@ -167,7 +167,7 @@
// jumping to the target address intended by the caller and that was
// overwritten by the address of DebugBreakXXX.
ExternalReference after_break_target =
- ExternalReference(Debug_Address::AfterBreakTarget(), masm->isolate());
+ ExternalReference::debug_after_break_target_address(masm->isolate());
__ jmp(Operand::StaticVariable(after_break_target));
}
@@ -308,8 +308,8 @@
void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
ExternalReference restarter_frame_function_slot =
- ExternalReference(Debug_Address::RestarterFrameFunctionPointer(),
- masm->isolate());
+ ExternalReference::debug_restarter_frame_function_pointer_address(
+ masm->isolate());
__ mov(Operand::StaticVariable(restarter_frame_function_slot), Immediate(0));
// We do not know our frame height, but set esp based on ebp.
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 906ee3e..1d97d8a 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -3041,8 +3041,7 @@
key,
instr->hydrogen()->key()->representation(),
elements_kind,
- 0,
- instr->additional_index()));
+ instr->base_offset()));
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
XMMRegister result(ToDoubleRegister(instr->result()));
@@ -3105,14 +3104,11 @@
void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
- int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
- sizeof(kHoleNanLower32);
Operand hole_check_operand = BuildFastArrayOperand(
instr->elements(), instr->key(),
instr->hydrogen()->key()->representation(),
FAST_DOUBLE_ELEMENTS,
- offset,
- instr->additional_index());
+ instr->base_offset() + sizeof(kHoleNanLower32));
__ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
DeoptimizeIf(equal, instr->environment());
}
@@ -3122,8 +3118,7 @@
instr->key(),
instr->hydrogen()->key()->representation(),
FAST_DOUBLE_ELEMENTS,
- FixedDoubleArray::kHeaderSize - kHeapObjectTag,
- instr->additional_index());
+ instr->base_offset());
XMMRegister result = ToDoubleRegister(instr->result());
__ movsd(result, double_load_operand);
}
@@ -3138,8 +3133,7 @@
instr->key(),
instr->hydrogen()->key()->representation(),
FAST_ELEMENTS,
- FixedArray::kHeaderSize - kHeapObjectTag,
- instr->additional_index()));
+ instr->base_offset()));
// Check for the hole value.
if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -3170,13 +3164,9 @@
LOperand* key,
Representation key_representation,
ElementsKind elements_kind,
- uint32_t offset,
- uint32_t additional_index) {
+ uint32_t base_offset) {
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));
@@ -3184,8 +3174,8 @@
Abort(kArrayIndexConstantValueTooBig);
}
return Operand(elements_pointer_reg,
- ((constant_value + additional_index) << shift_size)
- + offset);
+ ((constant_value) << shift_size)
+ + base_offset);
} else {
// Take the tag bit into account while computing the shift size.
if (key_representation.IsSmi() && (shift_size >= 1)) {
@@ -3195,7 +3185,7 @@
return Operand(elements_pointer_reg,
ToRegister(key),
scale_factor,
- offset + (additional_index << element_shift_size));
+ base_offset);
}
}
@@ -4122,8 +4112,7 @@
key,
instr->hydrogen()->key()->representation(),
elements_kind,
- 0,
- instr->additional_index()));
+ instr->base_offset()));
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
XMMRegister xmm_scratch = double_scratch0();
@@ -4182,8 +4171,7 @@
instr->key(),
instr->hydrogen()->key()->representation(),
FAST_DOUBLE_ELEMENTS,
- FixedDoubleArray::kHeaderSize - kHeapObjectTag,
- instr->additional_index());
+ instr->base_offset());
XMMRegister value = ToDoubleRegister(instr->value());
@@ -4210,8 +4198,7 @@
instr->key(),
instr->hydrogen()->key()->representation(),
FAST_ELEMENTS,
- FixedArray::kHeaderSize - kHeapObjectTag,
- instr->additional_index());
+ instr->base_offset());
if (instr->value()->IsRegister()) {
__ mov(operand, ToRegister(instr->value()));
} else {
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index d771893..d5a192e 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -241,8 +241,7 @@
LOperand* key,
Representation key_representation,
ElementsKind elements_kind,
- uint32_t offset,
- uint32_t additional_index = 0);
+ uint32_t base_offset);
Operand BuildSeqStringOperand(Register string,
LOperand* index,
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 067863d..76a107d 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -386,7 +386,7 @@
stream->Add("[");
key()->PrintTo(stream);
if (hydrogen()->IsDehoisted()) {
- stream->Add(" + %d]", additional_index());
+ stream->Add(" + %d]", base_offset());
} else {
stream->Add("]");
}
@@ -398,7 +398,7 @@
stream->Add("[");
key()->PrintTo(stream);
if (hydrogen()->IsDehoisted()) {
- stream->Add(" + %d] <-", additional_index());
+ stream->Add(" + %d] <-", base_offset());
} else {
stream->Add("] <- ");
}
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index ae80138..6cfe3e1 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -1642,7 +1642,7 @@
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- uint32_t additional_index() const { return hydrogen()->index_offset(); }
+ uint32_t base_offset() const { return hydrogen()->base_offset(); }
bool key_is_smi() {
return hydrogen()->key()->representation().IsTagged();
}
@@ -2222,7 +2222,7 @@
DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- uint32_t additional_index() const { return hydrogen()->index_offset(); }
+ uint32_t base_offset() const { return hydrogen()->base_offset(); }
bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
};
diff --git a/src/ic.cc b/src/ic.cc
index a6efdab..463429e 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -207,7 +207,7 @@
return;
}
- holder->LocalLookupRealNamedProperty(name, lookup);
+ holder->LookupOwnRealNamedProperty(name, lookup);
if (lookup->IsFound()) {
ASSERT(!lookup->IsInterceptor());
return;
@@ -285,7 +285,7 @@
if (receiver->IsGlobalObject()) {
LookupResult lookup(isolate());
GlobalObject* global = GlobalObject::cast(*receiver);
- global->LocalLookupRealNamedProperty(name, &lookup);
+ global->LookupOwnRealNamedProperty(name, &lookup);
if (!lookup.IsFound()) return false;
PropertyCell* cell = global->GetPropertyCell(&lookup);
return cell->type()->IsConstant();
@@ -501,7 +501,14 @@
Code* target,
ConstantPoolArray* constant_pool) {
// Currently, CallIC doesn't have state changes.
- ASSERT(target->ic_state() == v8::internal::GENERIC);
+ if (target->ic_state() != v8::internal::MONOMORPHIC) return;
+ CallIC::State existing_state(target->extra_ic_state());
+
+ // Monomorphic array stubs don't need to be cleared because
+ // 1) the stub doesn't store information that should be cleared, and
+ // 2) the AllocationSite stored in the type feedback vector is immune
+ // from gc type feedback clearing.
+ ASSERT(existing_state.stub_type() == MONOMORPHIC_ARRAY);
}
@@ -1186,7 +1193,7 @@
receiver->Lookup(name, lookup);
if (lookup->IsFound()) {
if (lookup->IsInterceptor() && !HasInterceptorSetter(lookup->holder())) {
- receiver->LocalLookupRealNamedProperty(name, lookup);
+ receiver->LookupOwnRealNamedProperty(name, lookup);
if (!lookup->IsFound()) return false;
}
@@ -1794,6 +1801,15 @@
}
}
+ if (store_handle.is_null()) {
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate(),
+ store_handle,
+ Runtime::SetObjectProperty(
+ isolate(), object, key, value, NONE, strict_mode()),
+ Object);
+ }
+
if (!is_target_set()) {
if (*stub == *generic_stub()) {
TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
@@ -1803,32 +1819,55 @@
TRACE_IC("StoreIC", key);
}
- if (!store_handle.is_null()) return store_handle;
- Handle<Object> result;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate(),
- result,
- Runtime::SetObjectProperty(
- isolate(), object, key, value, NONE, strict_mode()),
- Object);
- return result;
+ return store_handle;
}
CallIC::State::State(ExtraICState extra_ic_state)
: argc_(ArgcBits::decode(extra_ic_state)),
- call_type_(CallTypeBits::decode(extra_ic_state)) {
+ call_type_(CallTypeBits::decode(extra_ic_state)),
+ stub_type_(StubTypeBits::decode(extra_ic_state)) {
}
ExtraICState CallIC::State::GetExtraICState() const {
ExtraICState extra_ic_state =
ArgcBits::encode(argc_) |
- CallTypeBits::encode(call_type_);
+ CallTypeBits::encode(call_type_) |
+ StubTypeBits::encode(stub_type_);
return extra_ic_state;
}
+bool CallIC::DoCustomHandler(Handle<Object> receiver,
+ Handle<Object> function,
+ Handle<FixedArray> vector,
+ Handle<Smi> slot,
+ const State& state) {
+ ASSERT(function->IsJSFunction());
+ // Are we the array function?
+ Handle<JSFunction> array_function = Handle<JSFunction>(
+ isolate()->context()->native_context()->array_function(), isolate());
+ if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
+ // Alter the slot.
+ Handle<AllocationSite> new_site = isolate()->factory()->NewAllocationSite();
+ vector->set(slot->value(), *new_site);
+ State new_state = state.ToMonomorphicArrayCallState();
+ CallICStub stub(isolate(), new_state);
+ set_target(*stub.GetCode());
+ Handle<String> name;
+ if (array_function->shared()->name()->IsString()) {
+ name = Handle<String>(String::cast(array_function->shared()->name()),
+ isolate());
+ }
+
+ TRACE_IC("CallIC (Array call)", name);
+ return true;
+ }
+ return false;
+}
+
+
void CallIC::HandleMiss(Handle<Object> receiver,
Handle<Object> function,
Handle<FixedArray> vector,
@@ -1836,18 +1875,33 @@
State state(target()->extra_ic_state());
Object* feedback = vector->get(slot->value());
- if (feedback->IsJSFunction() || !function->IsJSFunction()) {
+ if (feedback->IsJSFunction() || !function->IsJSFunction() ||
+ state.stub_type() != DEFAULT) {
// We are going generic.
- ASSERT(!function->IsJSFunction() || *function != feedback);
-
vector->set(slot->value(),
*TypeFeedbackInfo::MegamorphicSentinel(isolate()),
SKIP_WRITE_BARRIER);
+
+ State new_state = state.ToGenericState();
+ if (new_state != state) {
+ // Only happens when the array ic goes generic.
+ ASSERT(state.stub_type() == MONOMORPHIC_ARRAY);
+ CallICStub stub(isolate(), new_state);
+ Handle<Code> code = stub.GetCode();
+ set_target(*code);
+ }
+
TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic");
} else {
// If we came here feedback must be the uninitialized sentinel,
// and we are going monomorphic.
ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()));
+
+ // Do we want to install a custom handler?
+ if (DoCustomHandler(receiver, function, vector, slot, state)) {
+ return;
+ }
+
Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
Handle<Object> name(js_function->shared()->name(), isolate());
TRACE_IC("CallIC", name);
@@ -1964,7 +2018,7 @@
#ifdef DEBUG
// The length property has to be a writable callback property.
LookupResult debug_lookup(isolate);
- receiver->LocalLookup(isolate->factory()->length_string(), &debug_lookup);
+ receiver->LookupOwn(isolate->factory()->length_string(), &debug_lookup);
ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly());
#endif
diff --git a/src/ic.h b/src/ic.h
index 197c32e..20b9b73 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -333,20 +333,34 @@
class CallIC: public IC {
public:
enum CallType { METHOD, FUNCTION };
+ enum StubType { DEFAULT, MONOMORPHIC_ARRAY };
class State V8_FINAL BASE_EMBEDDED {
public:
explicit State(ExtraICState extra_ic_state);
+ static State MonomorphicArrayCallState(int argc, CallType call_type) {
+ return State(argc, call_type, MONOMORPHIC_ARRAY);
+ }
+
static State DefaultCallState(int argc, CallType call_type) {
- return State(argc, call_type);
+ return State(argc, call_type, DEFAULT);
}
- static State MegamorphicCallState(int argc, CallType call_type) {
- return State(argc, call_type);
+ // Transition from the current state to another.
+ State ToGenericState() const {
+ return DefaultCallState(arg_count(), call_type());
}
- InlineCacheState GetICState() const { return ::v8::internal::GENERIC; }
+ State ToMonomorphicArrayCallState() const {
+ return MonomorphicArrayCallState(arg_count(), call_type());
+ }
+
+ InlineCacheState GetICState() const {
+ return stub_type_ == CallIC::DEFAULT
+ ? ::v8::internal::GENERIC
+ : ::v8::internal::MONOMORPHIC;
+ }
ExtraICState GetExtraICState() const;
@@ -355,6 +369,7 @@
int arg_count() const { return argc_; }
CallType call_type() const { return call_type_; }
+ StubType stub_type() const { return stub_type_; }
bool CallAsMethod() const { return call_type_ == METHOD; }
@@ -370,17 +385,20 @@
}
private:
- State(int argc,
- CallType call_type)
+ State(int argc, CallType call_type, StubType stub_type)
: argc_(argc),
- call_type_(call_type) {
+ call_type_(call_type),
+ stub_type_(stub_type) {
}
class ArgcBits: public BitField<int, 0, Code::kArgumentsBits> {};
class CallTypeBits: public BitField<CallType, Code::kArgumentsBits, 1> {};
+ class StubTypeBits:
+ public BitField<StubType, Code::kArgumentsBits + 1, 1> {}; // NOLINT
const int argc_;
const CallType call_type_;
+ const StubType stub_type_;
};
explicit CallIC(Isolate* isolate)
@@ -392,6 +410,13 @@
Handle<FixedArray> vector,
Handle<Smi> slot);
+ // Returns true if a custom handler was installed.
+ bool DoCustomHandler(Handle<Object> receiver,
+ Handle<Object> function,
+ Handle<FixedArray> vector,
+ Handle<Smi> slot,
+ const State& new_state);
+
// Code generator routines.
static Handle<Code> initialize_stub(Isolate* isolate,
int argc,
diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc
index b726a9b..7bce832 100644
--- a/src/incremental-marking.cc
+++ b/src/incremental-marking.cc
@@ -463,7 +463,7 @@
return FLAG_incremental_marking &&
FLAG_incremental_marking_steps &&
heap_->gc_state() == Heap::NOT_IN_GC &&
- !Serializer::enabled(heap_->isolate()) &&
+ !heap_->isolate()->serializer_enabled() &&
heap_->isolate()->IsInitialized() &&
heap_->PromotedSpaceSizeOfObjects() > kActivationThreshold;
}
@@ -541,7 +541,7 @@
ASSERT(FLAG_incremental_marking_steps);
ASSERT(state_ == STOPPED);
ASSERT(heap_->gc_state() == Heap::NOT_IN_GC);
- ASSERT(!Serializer::enabled(heap_->isolate()));
+ ASSERT(!heap_->isolate()->serializer_enabled());
ASSERT(heap_->isolate()->IsInitialized());
ResetStepCounters();
diff --git a/src/isolate.cc b/src/isolate.cc
index f7605d8..9572046 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -494,30 +494,30 @@
// tag.
column_offset += script->column_offset()->value();
}
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
stack_frame, column_key,
Handle<Smi>(Smi::FromInt(column_offset + 1), this), NONE).Check();
}
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
stack_frame, line_key,
Handle<Smi>(Smi::FromInt(line_number + 1), this), NONE).Check();
}
if (options & StackTrace::kScriptId) {
Handle<Smi> script_id(script->id(), this);
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
stack_frame, script_id_key, script_id, NONE).Check();
}
if (options & StackTrace::kScriptName) {
Handle<Object> script_name(script->name(), this);
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
stack_frame, script_name_key, script_name, NONE).Check();
}
if (options & StackTrace::kScriptNameOrSourceURL) {
Handle<Object> result = Script::GetNameOrSourceURL(script);
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
stack_frame, script_name_or_source_url_key, result, NONE).Check();
}
@@ -526,7 +526,7 @@
if (!fun_name->BooleanValue()) {
fun_name = Handle<Object>(fun->shared()->inferred_name(), this);
}
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
stack_frame, function_key, fun_name, NONE).Check();
}
@@ -534,14 +534,14 @@
Handle<Object> is_eval =
script->compilation_type() == Script::COMPILATION_TYPE_EVAL ?
factory()->true_value() : factory()->false_value();
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
stack_frame, eval_key, is_eval, NONE).Check();
}
if (options & StackTrace::kIsConstructor) {
Handle<Object> is_constructor = (frames[i].is_constructor()) ?
factory()->true_value() : factory()->false_value();
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
stack_frame, constructor_key, is_constructor, NONE).Check();
}
@@ -1133,6 +1133,24 @@
} else {
OS::PrintError("Extension or internal compilation error.\n");
}
+#ifdef OBJECT_PRINT
+ // Since comments and empty lines have been stripped from the source of
+ // builtins, print the actual source here so that line numbers match.
+ if (location->script()->source()->IsString()) {
+ Handle<String> src(String::cast(location->script()->source()));
+ PrintF("Failing script:\n");
+ int len = src->length();
+ int line_number = 1;
+ PrintF("%5d: ", line_number);
+ for (int i = 0; i < len; i++) {
+ uint16_t character = src->Get(i);
+ PrintF("%c", character);
+ if (character == '\n' && i < len - 2) {
+ PrintF("%5d: ", ++line_number);
+ }
+ }
+ }
+#endif
}
}
@@ -1457,8 +1475,8 @@
// TODO(bmeurer) Initialized lazily because it depends on flags; can
// be fixed once the default isolate cleanup is done.
random_number_generator_(NULL),
+ serializer_enabled_(false),
has_fatal_error_(false),
- use_crankshaft_(true),
initialized_from_snapshot_(false),
cpu_profiler_(NULL),
heap_profiler_(NULL),
@@ -1776,10 +1794,6 @@
has_fatal_error_ = false;
- use_crankshaft_ = FLAG_crankshaft
- && !Serializer::enabled(this)
- && CpuFeatures::SupportsCrankshaft();
-
if (function_entry_hook() != NULL) {
// When function entry hooking is in effect, we have to create the code
// stubs from scratch to get entry hooks, rather than loading the previously
@@ -1965,7 +1979,7 @@
kDeoptTableSerializeEntryCount - 1);
}
- if (!Serializer::enabled(this)) {
+ if (!serializer_enabled()) {
// Ensure that all stubs which need to be generated ahead of time, but
// cannot be serialized into the snapshot have been generated.
HandleScope scope(this);
@@ -2138,6 +2152,13 @@
}
+bool Isolate::use_crankshaft() const {
+ return FLAG_crankshaft &&
+ !serializer_enabled_ &&
+ CpuFeatures::SupportsCrankshaft();
+}
+
+
bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
Map* root_array_map =
get_initial_js_array_map(GetInitialFastElementsKind());
diff --git a/src/isolate.h b/src/isolate.h
index 3a67510..382cb5d 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -963,10 +963,18 @@
THREAD_LOCAL_TOP_ACCESSOR(LookupResult*, top_lookup_result)
+ void enable_serializer() {
+ // The serializer can only be enabled before the isolate init.
+ ASSERT(state_ != INITIALIZED);
+ serializer_enabled_ = true;
+ }
+
+ bool serializer_enabled() const { return serializer_enabled_; }
+
bool IsDead() { return has_fatal_error_; }
void SignalFatalError() { has_fatal_error_ = true; }
- bool use_crankshaft() const { return use_crankshaft_; }
+ bool use_crankshaft() const;
bool initialized_from_snapshot() { return initialized_from_snapshot_; }
@@ -1232,12 +1240,12 @@
CallInterfaceDescriptor* call_descriptors_;
RandomNumberGenerator* random_number_generator_;
+ // Whether the isolate has been created for snapshotting.
+ bool serializer_enabled_;
+
// True if fatal error has been signaled for this isolate.
bool has_fatal_error_;
- // True if we are using the Crankshaft optimizing compiler.
- bool use_crankshaft_;
-
// True if this isolate was initialized from a snapshot.
bool initialized_from_snapshot_;
diff --git a/src/json-parser.h b/src/json-parser.h
index f301778..792fddf 100644
--- a/src/json-parser.h
+++ b/src/json-parser.h
@@ -425,7 +425,7 @@
if (value.is_null()) return ReportUnexpectedCharacter();
}
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
json_object, key, value, NONE).Assert();
} while (MatchSkipWhiteSpace(','));
if (c0_ != '}') {
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index 7eb6746..1b51753 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -675,7 +675,7 @@
Handle<FixedArray> contents;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate_, contents,
- JSReceiver::GetKeys(object, JSReceiver::LOCAL_ONLY),
+ JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY),
EXCEPTION);
for (int i = 0; i < contents->length(); i++) {
diff --git a/src/lithium.cc b/src/lithium.cc
index c6d6413..0001e39 100644
--- a/src/lithium.cc
+++ b/src/lithium.cc
@@ -450,7 +450,7 @@
CodeEndLinePosInfoRecordEvent(*code, jit_handler_data));
CodeGenerator::PrintCode(code, info());
- ASSERT(!(Serializer::enabled(info()->isolate()) &&
+ ASSERT(!(info()->isolate()->serializer_enabled() &&
info()->GetMustNotHaveEagerFrame() &&
generator.NeedsEagerFrame()));
return code;
diff --git a/src/liveedit-debugger.js b/src/liveedit-debugger.js
index 021a4f0..07214f9 100644
--- a/src/liveedit-debugger.js
+++ b/src/liveedit-debugger.js
@@ -946,7 +946,9 @@
BLOCKED_ON_ACTIVE_STACK: 2,
BLOCKED_ON_OTHER_STACK: 3,
BLOCKED_UNDER_NATIVE_CODE: 4,
- REPLACED_ON_ACTIVE_STACK: 5
+ REPLACED_ON_ACTIVE_STACK: 5,
+ BLOCKED_UNDER_GENERATOR: 6,
+ BLOCKED_ACTIVE_GENERATOR: 7
};
FunctionPatchabilityStatus.SymbolName = function(code) {
diff --git a/src/liveedit.cc b/src/liveedit.cc
index e6bb4b2..f43f38a 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -939,13 +939,10 @@
// to code objects (that are never in new space) without worrying about
// write barriers.
Heap* heap = original->GetHeap();
- heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
- "liveedit.cc ReplaceCodeObject");
+ HeapIterator iterator(heap);
ASSERT(!heap->InNewSpace(*substitution));
- DisallowHeapAllocation no_allocation;
-
ReplacingVisitor visitor(*original, *substitution);
// Iterate over all roots. Stack frames may have pointer into original code,
@@ -955,7 +952,6 @@
// Now iterate over all pointers of all objects, including code_target
// implicit pointers.
- HeapIterator iterator(heap);
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
obj->Iterate(&visitor);
}
@@ -982,7 +978,7 @@
// If literal count didn't change, simply go over all functions
// and clear literal arrays.
ClearValuesVisitor visitor;
- IterateJSFunctions(*shared_info, &visitor);
+ IterateJSFunctions(shared_info, &visitor);
} else {
// When literal count changes, we have to create new array instances.
// Since we cannot create instances when iterating heap, we should first
@@ -1017,16 +1013,14 @@
// Iterates all function instances in the HEAP that refers to the
// provided shared_info.
template<typename Visitor>
- static void IterateJSFunctions(SharedFunctionInfo* shared_info,
+ static void IterateJSFunctions(Handle<SharedFunctionInfo> shared_info,
Visitor* visitor) {
- DisallowHeapAllocation no_allocation;
-
HeapIterator iterator(shared_info->GetHeap());
for (HeapObject* obj = iterator.next(); obj != NULL;
obj = iterator.next()) {
if (obj->IsJSFunction()) {
JSFunction* function = JSFunction::cast(obj);
- if (function->shared() == shared_info) {
+ if (function->shared() == *shared_info) {
visitor->visit(function);
}
}
@@ -1039,13 +1033,13 @@
Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
CountVisitor count_visitor;
count_visitor.count = 0;
- IterateJSFunctions(*shared_info, &count_visitor);
+ IterateJSFunctions(shared_info, &count_visitor);
int size = count_visitor.count;
Handle<FixedArray> result = isolate->factory()->NewFixedArray(size);
if (size > 0) {
CollectVisitor collect_visitor(result);
- IterateJSFunctions(*shared_info, &collect_visitor);
+ IterateJSFunctions(shared_info, &collect_visitor);
}
return result;
}
@@ -1165,7 +1159,7 @@
Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
- isolate->heap()->EnsureHeapIsIterable();
+ isolate->heap()->MakeHeapIterable();
if (IsJSFunctionCode(shared_info->code())) {
Handle<Code> code = compile_info_wrapper.GetFunctionCode();
@@ -1402,7 +1396,7 @@
info->set_end_position(new_function_end);
info->set_function_token_position(new_function_token_pos);
- info->GetIsolate()->heap()->EnsureHeapIsIterable();
+ info->GetIsolate()->heap()->MakeHeapIterable();
if (IsJSFunctionCode(info->code())) {
// Patch relocation info section of the code.
@@ -1682,11 +1676,6 @@
}
-static bool IsDropableFrame(StackFrame* frame) {
- return !frame->is_exit();
-}
-
-
// Describes a set of call frames that execute any of listed functions.
// Finding no such frames does not mean error.
class MultipleFunctionTarget {
@@ -1740,12 +1729,20 @@
bool target_frame_found = false;
int bottom_js_frame_index = top_frame_index;
- bool c_code_found = false;
+ bool non_droppable_frame_found = false;
+ LiveEdit::FunctionPatchabilityStatus non_droppable_reason;
for (; frame_index < frames.length(); frame_index++) {
StackFrame* frame = frames[frame_index];
- if (!IsDropableFrame(frame)) {
- c_code_found = true;
+ if (frame->is_exit()) {
+ non_droppable_frame_found = true;
+ non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE;
+ break;
+ }
+ if (frame->is_java_script() &&
+ JavaScriptFrame::cast(frame)->function()->shared()->is_generator()) {
+ non_droppable_frame_found = true;
+ non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
break;
}
if (target.MatchActivation(
@@ -1755,15 +1752,15 @@
}
}
- if (c_code_found) {
- // There is a C frames on stack. Check that there are no target frames
- // below them.
+ if (non_droppable_frame_found) {
+ // There is a C or generator frame on stack. We can't drop C frames, and we
+ // can't restart generators. Check that there are no target frames below
+ // them.
for (; frame_index < frames.length(); frame_index++) {
StackFrame* frame = frames[frame_index];
if (frame->is_java_script()) {
- if (target.MatchActivation(
- frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
- // Cannot drop frame under C frames.
+ if (target.MatchActivation(frame, non_droppable_reason)) {
+ // Fail.
return NULL;
}
}
@@ -1833,6 +1830,44 @@
}
+bool LiveEdit::FindActiveGenerators(Handle<FixedArray> shared_info_array,
+ Handle<FixedArray> result,
+ int len) {
+ Isolate* isolate = shared_info_array->GetIsolate();
+ bool found_suspended_activations = false;
+
+ ASSERT_LE(len, result->length());
+
+ FunctionPatchabilityStatus active = FUNCTION_BLOCKED_ACTIVE_GENERATOR;
+
+ Heap* heap = isolate->heap();
+ HeapIterator iterator(heap);
+ HeapObject* obj = NULL;
+ while ((obj = iterator.next()) != NULL) {
+ if (!obj->IsJSGeneratorObject()) continue;
+
+ JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
+ if (gen->is_closed()) continue;
+
+ HandleScope scope(isolate);
+
+ for (int i = 0; i < len; i++) {
+ Handle<JSValue> jsvalue =
+ Handle<JSValue>::cast(FixedArray::get(shared_info_array, i));
+ Handle<SharedFunctionInfo> shared =
+ UnwrapSharedFunctionInfoFromJSValue(jsvalue);
+
+ if (gen->function()->shared() == *shared) {
+ result->set(i, Smi::FromInt(active));
+ found_suspended_activations = true;
+ }
+ }
+ }
+
+ return found_suspended_activations;
+}
+
+
class InactiveThreadActivationsChecker : public ThreadVisitor {
public:
InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
@@ -1863,18 +1898,29 @@
Isolate* isolate = shared_info_array->GetIsolate();
int len = GetArrayLength(shared_info_array);
+ CHECK(shared_info_array->HasFastElements());
+ Handle<FixedArray> shared_info_array_elements(
+ FixedArray::cast(shared_info_array->elements()));
+
Handle<JSArray> result = isolate->factory()->NewJSArray(len);
+ Handle<FixedArray> result_elements =
+ JSObject::EnsureWritableFastElements(result);
// Fill the default values.
for (int i = 0; i < len; i++) {
- SetElementSloppy(
- result,
- i,
- Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH), isolate));
+ FunctionPatchabilityStatus status = FUNCTION_AVAILABLE_FOR_PATCH;
+ result_elements->set(i, Smi::FromInt(status));
}
+ // Scan the heap for active generators -- those that are either currently
+ // running (as we wouldn't want to restart them, because we don't know where
+ // to restart them from) or suspended. Fail if any one corresponds to the set
+ // of functions being edited.
+ if (FindActiveGenerators(shared_info_array_elements, result_elements, len)) {
+ return result;
+ }
- // First check inactive threads. Fail if some functions are blocked there.
+ // Check inactive threads. Fail if some functions are blocked there.
InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
result);
isolate->thread_manager()->IterateArchivedThreads(
@@ -1937,6 +1983,9 @@
if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) {
return "Function is blocked under native code";
}
+ if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR) {
+ return "Function is blocked under a generator activation";
+ }
return NULL;
}
diff --git a/src/liveedit.h b/src/liveedit.h
index e06688a..b22d01a 100644
--- a/src/liveedit.h
+++ b/src/liveedit.h
@@ -89,6 +89,11 @@
Handle<JSValue> orig_function_shared,
Handle<JSValue> subst_function_shared);
+ // Find open generator activations, and set corresponding "result" elements to
+ // FUNCTION_BLOCKED_ACTIVE_GENERATOR.
+ static bool FindActiveGenerators(Handle<FixedArray> shared_info_array,
+ Handle<FixedArray> result, int len);
+
// Checks listed functions on stack and return array with corresponding
// FunctionPatchabilityStatus statuses; extra array element may
// contain general error message. Modifies the current stack and
@@ -107,7 +112,9 @@
FUNCTION_BLOCKED_ON_ACTIVE_STACK = 2,
FUNCTION_BLOCKED_ON_OTHER_STACK = 3,
FUNCTION_BLOCKED_UNDER_NATIVE_CODE = 4,
- FUNCTION_REPLACED_ON_ACTIVE_STACK = 5
+ FUNCTION_REPLACED_ON_ACTIVE_STACK = 5,
+ FUNCTION_BLOCKED_UNDER_GENERATOR = 6,
+ FUNCTION_BLOCKED_ACTIVE_GENERATOR = 7
};
// Compares 2 strings line-by-line, then token-wise and returns diff in form
diff --git a/src/log.cc b/src/log.cc
index 623e08d..5c88cb4 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -230,6 +230,7 @@
virtual ~PerfBasicLogger();
virtual void CodeMoveEvent(Address from, Address to) { }
+ virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
virtual void CodeDeleteEvent(Address from) { }
private:
@@ -295,6 +296,7 @@
virtual ~PerfJitLogger();
virtual void CodeMoveEvent(Address from, Address to) { }
+ virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
virtual void CodeDeleteEvent(Address from) { }
private:
@@ -457,6 +459,7 @@
virtual ~LowLevelLogger();
virtual void CodeMoveEvent(Address from, Address to);
+ virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
virtual void CodeDeleteEvent(Address from);
virtual void SnapshotPositionEvent(Address addr, int pos);
virtual void CodeMovingGCEvent();
@@ -623,6 +626,7 @@
explicit JitLogger(JitCodeEventHandler code_event_handler);
virtual void CodeMoveEvent(Address from, Address to);
+ virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
virtual void CodeDeleteEvent(Address from);
virtual void AddCodeLinePosInfoEvent(
void* jit_handler_data,
@@ -1446,6 +1450,24 @@
}
+void Logger::CodeDisableOptEvent(Code* code,
+ SharedFunctionInfo* shared) {
+ PROFILER_LOG(CodeDisableOptEvent(code, shared));
+
+ if (!is_logging_code_events()) return;
+ CALL_LISTENERS(CodeDisableOptEvent(code, shared));
+
+ if (!FLAG_log_code || !log_->IsEnabled()) return;
+ Log::MessageBuilder msg(log_);
+ msg.Append("%s,", kLogEventsNames[CODE_DISABLE_OPT_EVENT]);
+ SmartArrayPointer<char> name =
+ shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+ msg.Append("\"%s\",", name.get());
+ msg.Append("\"%s\"\n", GetBailoutReason(shared->DisableOptimizationReason()));
+ msg.WriteToLogFile();
+}
+
+
void Logger::CodeMovingGCEvent() {
PROFILER_LOG(CodeMovingGCEvent());
diff --git a/src/log.h b/src/log.h
index b1a41e9..19adecb 100644
--- a/src/log.h
+++ b/src/log.h
@@ -79,6 +79,7 @@
#define LOG_EVENTS_AND_TAGS_LIST(V) \
V(CODE_CREATION_EVENT, "code-creation") \
+ V(CODE_DISABLE_OPT_EVENT, "code-disable-optimization") \
V(CODE_MOVE_EVENT, "code-move") \
V(CODE_DELETE_EVENT, "code-delete") \
V(CODE_MOVING_GC, "code-moving-gc") \
@@ -237,6 +238,8 @@
CompilationInfo* info,
Name* source, int line, int column);
void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
+ // Emits a code deoptimization event.
+ void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared);
void CodeMovingGCEvent();
// Emits a code create event for a RegExp.
void RegExpCodeCreateEvent(Code* code, String* source);
@@ -470,6 +473,7 @@
virtual void CodeDeleteEvent(Address from) = 0;
virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0;
virtual void CodeMovingGCEvent() = 0;
+ virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) = 0;
};
diff --git a/src/macros.py b/src/macros.py
index 39881fe..9b256cb 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -171,7 +171,7 @@
macro GLOBAL_PRIVATE(name) = (%CreateGlobalPrivateSymbol(name));
macro NEW_PRIVATE(name) = (%CreatePrivateSymbol(name));
macro IS_PRIVATE(sym) = (%SymbolIsPrivate(sym));
-macro HAS_PRIVATE(obj, sym) = (%HasLocalProperty(obj, sym));
+macro HAS_PRIVATE(obj, sym) = (%HasOwnProperty(obj, sym));
macro GET_PRIVATE(obj, sym) = (obj[sym]);
macro SET_PRIVATE(obj, sym, val) = (obj[sym] = val);
macro DELETE_PRIVATE(obj, sym) = (delete obj[sym]);
diff --git a/src/messages.js b/src/messages.js
index d20b34b..859bc0d 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -1240,7 +1240,7 @@
function GetPropertyWithoutInvokingMonkeyGetters(error, name) {
var current = error;
// Climb the prototype chain until we find the holder.
- while (current && !%HasLocalProperty(current, name)) {
+ while (current && !%HasOwnProperty(current, name)) {
current = %GetPrototype(current);
}
if (IS_NULL(current)) return UNDEFINED;
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 6e033b9..f47ab38 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -3094,11 +3094,13 @@
}
-void CallFunctionStub::Generate(MacroAssembler* masm) {
+static void CallFunctionNoFeedback(MacroAssembler* masm,
+ int argc, bool needs_checks,
+ bool call_as_method) {
// a1 : the function to call
Label slow, non_function, wrap, cont;
- if (NeedsChecks()) {
+ if (needs_checks) {
// Check that the function is really a JavaScript function.
// a1: pushed function (to be verified)
__ JumpIfSmi(a1, &non_function);
@@ -3110,18 +3112,17 @@
// Fast-case: Invoke the function now.
// a1: pushed function
- int argc = argc_;
ParameterCount actual(argc);
- if (CallAsMethod()) {
- if (NeedsChecks()) {
+ if (call_as_method) {
+ if (needs_checks) {
EmitContinueIfStrictOrNative(masm, &cont);
}
// Compute the receiver in sloppy mode.
__ lw(a3, MemOperand(sp, argc * kPointerSize));
- if (NeedsChecks()) {
+ if (needs_checks) {
__ JumpIfSmi(a3, &wrap);
__ GetObjectType(a3, t0, t0);
__ Branch(&wrap, lt, t0, Operand(FIRST_SPEC_OBJECT_TYPE));
@@ -3134,13 +3135,13 @@
__ InvokeFunction(a1, actual, JUMP_FUNCTION, NullCallWrapper());
- if (NeedsChecks()) {
+ if (needs_checks) {
// Slow-case: Non-function called.
__ bind(&slow);
EmitSlowCase(masm, argc, &non_function);
}
- if (CallAsMethod()) {
+ if (call_as_method) {
__ bind(&wrap);
// Wrap the receiver and patch it back onto the stack.
EmitWrapCase(masm, argc, &cont);
@@ -3148,6 +3149,11 @@
}
+void CallFunctionStub::Generate(MacroAssembler* masm) {
+ CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod());
+}
+
+
void CallConstructStub::Generate(MacroAssembler* masm) {
// a0 : number of arguments
// a1 : the function to call
@@ -3207,8 +3213,8 @@
__ bind(&do_call);
// Set expected number of arguments to zero (not changing r0).
__ li(a2, Operand(0, RelocInfo::NONE32));
- __ Jump(isolate()->builtins()->ArgumentsAdaptorTrampoline(),
- RelocInfo::CODE_TARGET);
+ __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
+ RelocInfo::CODE_TARGET);
}
@@ -3221,6 +3227,51 @@
}
+void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
+ // a1 - function
+ // a2 - feedback vector
+ // a3 - slot id
+ __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, at);
+ __ Branch(miss, ne, a1, Operand(at));
+
+ __ li(a0, Operand(arg_count()));
+ __ sll(at, a3, kPointerSizeLog2 - kSmiTagSize);
+ __ Addu(at, a2, Operand(at));
+ __ lw(a2, FieldMemOperand(at, FixedArray::kHeaderSize));
+ // Verify that a2 contains an AllocationSite
+ __ AssertUndefinedOrAllocationSite(a2, at);
+ ArrayConstructorStub stub(masm->isolate(), arg_count());
+ __ TailCallStub(&stub);
+}
+
+
+void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) {
+ // a1 - function
+ // a2 - feedback vector
+ // a3 - slot id
+ Label miss;
+
+ if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) {
+ Generate_MonomorphicArray(masm, &miss);
+ } else {
+ // So far there is only one customer for our custom feedback scheme.
+ UNREACHABLE();
+ }
+
+ __ bind(&miss);
+ GenerateMiss(masm);
+
+ // The slow case, we need this no matter what to complete a call after a miss.
+ CallFunctionNoFeedback(masm,
+ arg_count(),
+ true,
+ CallAsMethod());
+
+ // Unreachable.
+ __ stop("Unexpected code address");
+}
+
+
void CallICStub::Generate(MacroAssembler* masm) {
// r1 - function
// r3 - slot id (Smi)
@@ -3232,6 +3283,11 @@
EmitLoadTypeFeedbackVector(masm, a2);
+ if (state_.stub_type() != CallIC::DEFAULT) {
+ Generate_CustomFeedbackCall(masm);
+ return;
+ }
+
// The checks. First, does r1 match the recorded monomorphic target?
__ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
__ Addu(t0, a2, Operand(t0));
diff --git a/src/mips/debug-mips.cc b/src/mips/debug-mips.cc
index fcb5643..0ef9e29 100644
--- a/src/mips/debug-mips.cc
+++ b/src/mips/debug-mips.cc
@@ -155,8 +155,9 @@
// Now that the break point has been handled, resume normal execution by
// jumping to the target address intended by the caller and that was
// overwritten by the address of DebugBreakXXX.
- __ li(t9, Operand(
- ExternalReference(Debug_Address::AfterBreakTarget(), masm->isolate())));
+ ExternalReference after_break_target =
+ ExternalReference::debug_after_break_target_address(masm->isolate());
+ __ li(t9, Operand(after_break_target));
__ lw(t9, MemOperand(t9));
__ Jump(t9);
}
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index b5d8fa8..fd30b1a 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -3110,16 +3110,13 @@
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 = IsFixedTypedArrayElementsKind(elements_kind)
- ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
- : 0;
+ int base_offset = instr->base_offset();
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS ||
elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
- int base_offset =
- (instr->additional_index() << element_size_shift) + additional_offset;
+ int base_offset = instr->base_offset();
FPURegister result = ToDoubleRegister(instr->result());
if (key_is_constant) {
__ Addu(scratch0(), external_pointer, constant_key << element_size_shift);
@@ -3131,15 +3128,14 @@
elements_kind == FLOAT32_ELEMENTS) {
__ lwc1(result, MemOperand(scratch0(), base_offset));
__ cvt_d_s(result, result);
- } else { // loading doubles, not floats.
+ } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
__ ldc1(result, MemOperand(scratch0(), base_offset));
}
} else {
Register result = ToRegister(instr->result());
MemOperand mem_operand = PrepareKeyedOperand(
key, external_pointer, key_is_constant, constant_key,
- element_size_shift, shift_size,
- instr->additional_index(), additional_offset);
+ element_size_shift, shift_size, base_offset);
switch (elements_kind) {
case EXTERNAL_INT8_ELEMENTS:
case INT8_ELEMENTS:
@@ -3199,15 +3195,13 @@
int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
- int base_offset =
- FixedDoubleArray::kHeaderSize - kHeapObjectTag +
- (instr->additional_index() << element_size_shift);
+ int base_offset = instr->base_offset();
if (key_is_constant) {
int constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
Abort(kArrayIndexConstantValueTooBig);
}
- base_offset += constant_key << element_size_shift;
+ base_offset += constant_key * kDoubleSize;
}
__ Addu(scratch, elements, Operand(base_offset));
@@ -3233,12 +3227,11 @@
Register result = ToRegister(instr->result());
Register scratch = scratch0();
Register store_base = scratch;
- int offset = 0;
+ int offset = instr->base_offset();
if (instr->key()->IsConstantOperand()) {
LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
- offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
- instr->additional_index());
+ offset += ToInteger32(const_operand) * kPointerSize;
store_base = elements;
} else {
Register key = ToRegister(instr->key());
@@ -3253,9 +3246,8 @@
__ sll(scratch, key, kPointerSizeLog2);
__ addu(scratch, elements, scratch);
}
- offset = FixedArray::OffsetOfElementAt(instr->additional_index());
}
- __ lw(result, FieldMemOperand(store_base, offset));
+ __ lw(result, MemOperand(store_base, offset));
// Check for the hole value.
if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -3287,34 +3279,12 @@
int constant_key,
int element_size,
int shift_size,
- int additional_index,
- int additional_offset) {
- int base_offset = (additional_index << element_size) + additional_offset;
+ int base_offset) {
if (key_is_constant) {
- return MemOperand(base,
- base_offset + (constant_key << element_size));
+ return MemOperand(base, (constant_key << element_size) + base_offset);
}
- 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);
- // Key can be negative, so using sra here.
- __ sra(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) {
+ if (base_offset == 0) {
if (shift_size >= 0) {
__ sll(scratch0(), key, shift_size);
__ Addu(scratch0(), base, scratch0());
@@ -3328,14 +3298,14 @@
}
if (shift_size >= 0) {
- __ sll(scratch0(), scratch0(), shift_size);
+ __ sll(scratch0(), key, shift_size);
__ Addu(scratch0(), base, scratch0());
- return MemOperand(scratch0());
+ return MemOperand(scratch0(), base_offset);
} else {
ASSERT_EQ(-1, shift_size);
- __ srl(scratch0(), scratch0(), 1);
+ __ sra(scratch0(), key, 1);
__ Addu(scratch0(), base, scratch0());
- return MemOperand(scratch0());
+ return MemOperand(scratch0(), base_offset);
}
}
@@ -4208,16 +4178,12 @@
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 = IsFixedTypedArrayElementsKind(elements_kind)
- ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
- : 0;
+ int base_offset = instr->base_offset();
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS ||
elements_kind == EXTERNAL_FLOAT64_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) {
@@ -4244,7 +4210,7 @@
MemOperand mem_operand = PrepareKeyedOperand(
key, external_pointer, key_is_constant, constant_key,
element_size_shift, shift_size,
- instr->additional_index(), additional_offset);
+ base_offset);
switch (elements_kind) {
case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
case EXTERNAL_INT8_ELEMENTS:
@@ -4291,6 +4257,7 @@
Register scratch = scratch0();
DoubleRegister double_scratch = double_scratch0();
bool key_is_constant = instr->key()->IsConstantOperand();
+ int base_offset = instr->base_offset();
Label not_nan, done;
// Calculate the effective address of the slot in the array to store the
@@ -4302,13 +4269,11 @@
Abort(kArrayIndexConstantValueTooBig);
}
__ Addu(scratch, elements,
- Operand((constant_key << element_size_shift) +
- FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+ Operand((constant_key << element_size_shift) + base_offset));
} else {
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
- __ Addu(scratch, elements,
- Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+ __ Addu(scratch, elements, Operand(base_offset));
__ sll(at, ToRegister(instr->key()), shift_size);
__ Addu(scratch, scratch, at);
}
@@ -4323,14 +4288,12 @@
__ bind(&is_nan);
__ LoadRoot(at, Heap::kNanValueRootIndex);
__ ldc1(double_scratch, FieldMemOperand(at, HeapNumber::kValueOffset));
- __ sdc1(double_scratch, MemOperand(scratch, instr->additional_index() <<
- element_size_shift));
+ __ sdc1(double_scratch, MemOperand(scratch, 0));
__ Branch(&done);
}
__ bind(¬_nan);
- __ sdc1(value, MemOperand(scratch, instr->additional_index() <<
- element_size_shift));
+ __ sdc1(value, MemOperand(scratch, 0));
__ bind(&done);
}
@@ -4342,14 +4305,13 @@
: no_reg;
Register scratch = scratch0();
Register store_base = scratch;
- int offset = 0;
+ int offset = instr->base_offset();
// Do the store.
if (instr->key()->IsConstantOperand()) {
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
- offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
- instr->additional_index());
+ offset += ToInteger32(const_operand) * kPointerSize;
store_base = elements;
} else {
// Even though the HLoadKeyed instruction forces the input
@@ -4363,16 +4325,15 @@
__ sll(scratch, key, kPointerSizeLog2);
__ addu(scratch, elements, scratch);
}
- offset = FixedArray::OffsetOfElementAt(instr->additional_index());
}
- __ sw(value, FieldMemOperand(store_base, offset));
+ __ sw(value, MemOperand(store_base, offset));
if (instr->hydrogen()->NeedsWriteBarrier()) {
SmiCheck check_needed =
instr->hydrogen()->value()->IsHeapObject()
? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
// Compute address of modified element and store it into key register.
- __ Addu(key, store_base, Operand(offset - kHeapObjectTag));
+ __ Addu(key, store_base, Operand(offset));
__ RecordWrite(elements,
key,
value,
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index 7c52d81..0657fad 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -132,8 +132,7 @@
int constant_key,
int element_size,
int shift_size,
- int additional_index,
- int additional_offset);
+ int base_offset);
// Emit frame translation commands for an environment.
void WriteTranslation(LEnvironment* environment, Translation* translation);
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 97b91fa..28cd6dd 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -342,7 +342,7 @@
stream->Add("[");
key()->PrintTo(stream);
if (hydrogen()->IsDehoisted()) {
- stream->Add(" + %d]", additional_index());
+ stream->Add(" + %d]", base_offset());
} else {
stream->Add("]");
}
@@ -354,7 +354,7 @@
stream->Add("[");
key()->PrintTo(stream);
if (hydrogen()->IsDehoisted()) {
- stream->Add(" + %d] <-", additional_index());
+ stream->Add(" + %d] <-", base_offset());
} else {
stream->Add("] <- ");
}
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index 8133c31..ad2a1e7 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -1609,7 +1609,7 @@
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
virtual void PrintDataTo(StringStream* stream);
- uint32_t additional_index() const { return hydrogen()->index_offset(); }
+ uint32_t base_offset() const { return hydrogen()->base_offset(); }
};
@@ -2178,7 +2178,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
- uint32_t additional_index() const { return hydrogen()->index_offset(); }
+ uint32_t base_offset() const { return hydrogen()->base_offset(); }
};
diff --git a/src/mirror-debugger.js b/src/mirror-debugger.js
index 2695e01..b1f67ac 100644
--- a/src/mirror-debugger.js
+++ b/src/mirror-debugger.js
@@ -676,9 +676,9 @@
// Find all the named properties.
if (kind & PropertyKind.Named) {
- // Get all the local property names except for private symbols.
+ // Get all own property names except for private symbols.
propertyNames =
- %GetLocalPropertyNames(this.value_, PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL);
+ %GetOwnPropertyNames(this.value_, PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL);
total += propertyNames.length;
// Get names for named interceptor properties if any.
@@ -694,8 +694,8 @@
// Find all the indexed properties.
if (kind & PropertyKind.Indexed) {
- // Get the local element names.
- elementNames = %GetLocalElementNames(this.value_);
+ // Get own element names.
+ elementNames = %GetOwnElementNames(this.value_);
total += elementNames.length;
// Get names for indexed interceptor properties.
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index 4f8d414..e04d8da 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -296,106 +296,103 @@
i::FLAG_logfile_per_isolate = false;
Isolate* isolate = v8::Isolate::New();
- isolate->Enter();
- i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- i::Serializer::RequestEnable(internal_isolate);
- Persistent<Context> context;
- {
- HandleScope handle_scope(isolate);
- context.Reset(isolate, Context::New(isolate));
- }
+ { Isolate::Scope isolate_scope(isolate);
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ internal_isolate->enable_serializer();
- if (context.IsEmpty()) {
- fprintf(stderr,
- "\nException thrown while compiling natives - see above.\n\n");
- exit(1);
- }
- if (i::FLAG_extra_code != NULL) {
- // Capture 100 frames if anything happens.
- V8::SetCaptureStackTraceForUncaughtExceptions(true, 100);
- HandleScope scope(isolate);
- v8::Context::Scope cscope(v8::Local<v8::Context>::New(isolate, context));
- const char* name = i::FLAG_extra_code;
- FILE* file = i::OS::FOpen(name, "rb");
- if (file == NULL) {
- fprintf(stderr, "Failed to open '%s': errno %d\n", name, errno);
- exit(1);
+ Persistent<Context> context;
+ {
+ HandleScope handle_scope(isolate);
+ context.Reset(isolate, Context::New(isolate));
}
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
- rewind(file);
-
- char* chars = new char[size + 1];
- chars[size] = '\0';
- for (int i = 0; i < size;) {
- int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
- if (read < 0) {
- fprintf(stderr, "Failed to read '%s': errno %d\n", name, errno);
+ if (context.IsEmpty()) {
+ fprintf(stderr,
+ "\nException thrown while compiling natives - see above.\n\n");
+ exit(1);
+ }
+ if (i::FLAG_extra_code != NULL) {
+ // Capture 100 frames if anything happens.
+ V8::SetCaptureStackTraceForUncaughtExceptions(true, 100);
+ HandleScope scope(isolate);
+ v8::Context::Scope cscope(v8::Local<v8::Context>::New(isolate, context));
+ const char* name = i::FLAG_extra_code;
+ FILE* file = i::OS::FOpen(name, "rb");
+ if (file == NULL) {
+ fprintf(stderr, "Failed to open '%s': errno %d\n", name, errno);
exit(1);
}
- i += read;
+
+ fseek(file, 0, SEEK_END);
+ int size = ftell(file);
+ rewind(file);
+
+ char* chars = new char[size + 1];
+ chars[size] = '\0';
+ for (int i = 0; i < size;) {
+ int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
+ if (read < 0) {
+ fprintf(stderr, "Failed to read '%s': errno %d\n", name, errno);
+ exit(1);
+ }
+ i += read;
+ }
+ fclose(file);
+ Local<String> source = String::NewFromUtf8(isolate, chars);
+ TryCatch try_catch;
+ Local<Script> script = Script::Compile(source);
+ if (try_catch.HasCaught()) {
+ fprintf(stderr, "Failure compiling '%s'\n", name);
+ DumpException(try_catch.Message());
+ exit(1);
+ }
+ script->Run();
+ if (try_catch.HasCaught()) {
+ fprintf(stderr, "Failure running '%s'\n", name);
+ DumpException(try_catch.Message());
+ exit(1);
+ }
}
- fclose(file);
- Local<String> source = String::NewFromUtf8(isolate, chars);
- TryCatch try_catch;
- Local<Script> script = Script::Compile(source);
- if (try_catch.HasCaught()) {
- fprintf(stderr, "Failure compiling '%s'\n", name);
- DumpException(try_catch.Message());
- exit(1);
+ // Make sure all builtin scripts are cached.
+ { HandleScope scope(isolate);
+ for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
+ internal_isolate->bootstrapper()->NativesSourceLookup(i);
+ }
}
- script->Run();
- if (try_catch.HasCaught()) {
- fprintf(stderr, "Failure running '%s'\n", name);
- DumpException(try_catch.Message());
- exit(1);
+ // If we don't do this then we end up with a stray root pointing at the
+ // context even after we have disposed of the context.
+ internal_isolate->heap()->CollectAllGarbage(
+ i::Heap::kNoGCFlags, "mksnapshot");
+ i::Object* raw_context = *v8::Utils::OpenPersistent(context);
+ context.Reset();
+
+ // This results in a somewhat smaller snapshot, probably because it gets
+ // rid of some things that are cached between garbage collections.
+ i::List<char> snapshot_data;
+ ListSnapshotSink snapshot_sink(&snapshot_data);
+ i::StartupSerializer ser(internal_isolate, &snapshot_sink);
+ ser.SerializeStrongReferences();
+
+ i::List<char> context_data;
+ ListSnapshotSink contex_sink(&context_data);
+ i::PartialSerializer context_ser(internal_isolate, &ser, &contex_sink);
+ context_ser.Serialize(&raw_context);
+ ser.SerializeWeakReferences();
+
+ {
+ SnapshotWriter writer(argv[1]);
+ writer.SetOmit(i::FLAG_omit);
+ if (i::FLAG_raw_file && i::FLAG_raw_context_file)
+ writer.SetRawFiles(i::FLAG_raw_file, i::FLAG_raw_context_file);
+ #ifdef COMPRESS_STARTUP_DATA_BZ2
+ BZip2Compressor bzip2;
+ writer.SetCompressor(&bzip2);
+ #endif
+ writer.WriteSnapshot(snapshot_data, ser, context_data, context_ser);
}
}
- // Make sure all builtin scripts are cached.
- { HandleScope scope(isolate);
- for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
- internal_isolate->bootstrapper()->NativesSourceLookup(i);
- }
- }
- // If we don't do this then we end up with a stray root pointing at the
- // context even after we have disposed of the context.
- internal_isolate->heap()->CollectAllGarbage(
- i::Heap::kNoGCFlags, "mksnapshot");
- i::Object* raw_context = *v8::Utils::OpenPersistent(context);
- context.Reset();
- // This results in a somewhat smaller snapshot, probably because it gets rid
- // of some things that are cached between garbage collections.
- i::List<char> snapshot_data;
- ListSnapshotSink snapshot_sink(&snapshot_data);
- i::StartupSerializer ser(internal_isolate, &snapshot_sink);
- ser.SerializeStrongReferences();
-
- i::List<char> context_data;
- ListSnapshotSink contex_sink(&context_data);
- i::PartialSerializer context_ser(internal_isolate, &ser, &contex_sink);
- context_ser.Serialize(&raw_context);
- ser.SerializeWeakReferences();
-
- {
- SnapshotWriter writer(argv[1]);
- writer.SetOmit(i::FLAG_omit);
- if (i::FLAG_raw_file && i::FLAG_raw_context_file)
- writer.SetRawFiles(i::FLAG_raw_file, i::FLAG_raw_context_file);
-#ifdef COMPRESS_STARTUP_DATA_BZ2
- BZip2Compressor bzip2;
- writer.SetCompressor(&bzip2);
-#endif
- writer.WriteSnapshot(snapshot_data, ser, context_data, context_ser);
- }
-
- isolate->Exit();
isolate->Dispose();
- // TODO(svenpanne) Alas, we can't cleanly dispose V8 here, because
- // Serializer::code_address_map_ is static (a.k.a. a global variable), and
- // disposing that would involve accessing the Isolate just disposed.
- // code_address_map_ really has to be an instance variable...
- // V8::Dispose();
+ V8::Dispose();
return 0;
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index dca3eca..0be46bc 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -5715,6 +5715,14 @@
return continuation() > 0;
}
+bool JSGeneratorObject::is_closed() {
+ return continuation() == kGeneratorClosed;
+}
+
+bool JSGeneratorObject::is_executing() {
+ return continuation() == kGeneratorExecuting;
+}
+
JSGeneratorObject* JSGeneratorObject::cast(Object* obj) {
ASSERT(obj->IsJSGeneratorObject());
ASSERT(HeapObject::cast(obj)->Size() == JSGeneratorObject::kSize);
@@ -6276,13 +6284,12 @@
}
-bool JSReceiver::HasLocalProperty(Handle<JSReceiver> object,
- Handle<Name> name) {
+bool JSReceiver::HasOwnProperty(Handle<JSReceiver> object, Handle<Name> name) {
if (object->IsJSProxy()) {
Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
return JSProxy::HasPropertyWithHandler(proxy, name);
}
- return GetLocalPropertyAttribute(object, name) != ABSENT;
+ return GetOwnPropertyAttribute(object, name) != ABSENT;
}
@@ -6341,7 +6348,7 @@
}
-bool JSReceiver::HasLocalElement(Handle<JSReceiver> object, uint32_t index) {
+bool JSReceiver::HasOwnElement(Handle<JSReceiver> object, uint32_t index) {
if (object->IsJSProxy()) {
Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
return JSProxy::HasElementWithHandler(proxy, index);
@@ -6351,7 +6358,7 @@
}
-PropertyAttributes JSReceiver::GetLocalElementAttribute(
+PropertyAttributes JSReceiver::GetOwnElementAttribute(
Handle<JSReceiver> object, uint32_t index) {
if (object->IsJSProxy()) {
return JSProxy::GetElementAttributeWithHandler(
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index bb2e992..9234a9e 100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -290,7 +290,7 @@
if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub()
&& (target->ic_state() == MEGAMORPHIC || target->ic_state() == GENERIC ||
target->ic_state() == POLYMORPHIC || heap->flush_monomorphic_ics() ||
- Serializer::enabled(heap->isolate()) ||
+ heap->isolate()->serializer_enabled() ||
target->ic_age() != heap->global_ic_age() ||
target->is_invalidated_weak_stub())) {
IC::Clear(heap->isolate(), rinfo->pc(), rinfo->host()->constant_pool());
@@ -406,7 +406,7 @@
Map* map, HeapObject* object) {
Heap* heap = map->GetHeap();
Code* code = Code::cast(object);
- if (FLAG_age_code && !Serializer::enabled(heap->isolate())) {
+ if (FLAG_age_code && !heap->isolate()->serializer_enabled()) {
code->MakeOlder(heap->mark_compact_collector()->marking_parity());
}
code->CodeIterateBody<StaticVisitor>(heap);
diff --git a/src/objects.cc b/src/objects.cc
index 769d5fc..352e5d6 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -560,7 +560,7 @@
if (continue_search) {
result->holder()->LookupRealNamedProperty(name, &r);
} else {
- result->holder()->LocalLookupRealNamedProperty(name, &r);
+ result->holder()->LookupOwnRealNamedProperty(name, &r);
}
if (!r.IsFound()) break;
return GetPropertyAttributeWithFailedAccessCheck(
@@ -2014,10 +2014,10 @@
Handle<Object> value,
PropertyAttributes attributes,
StrictMode strict_mode) {
- // Check local property, ignore interceptor.
+ // Check own property, ignore interceptor.
Isolate* isolate = object->GetIsolate();
LookupResult result(isolate);
- object->LocalLookupRealNamedProperty(name, &result);
+ object->LookupOwnRealNamedProperty(name, &result);
if (!result.IsFound()) {
object->map()->LookupTransition(*object, *name, &result);
}
@@ -2996,7 +2996,7 @@
StrictMode strict_mode,
StoreFromKeyed store_mode) {
LookupResult result(object->GetIsolate());
- object->LocalLookup(name, &result, true);
+ object->LookupOwn(name, &result, true);
if (!result.IsFound()) {
object->map()->LookupTransition(JSObject::cast(*object), *name, &result);
}
@@ -3144,7 +3144,7 @@
Isolate* isolate = object->GetIsolate();
*done = false;
- // We could not find a local property so let's check whether there is an
+ // We could not find an own property, so let's check whether there is an
// accessor that wants to handle the property, or whether the property is
// read-only on the prototype chain.
LookupResult result(isolate);
@@ -3520,20 +3520,20 @@
}
-void JSObject::LocalLookupRealNamedProperty(Handle<Name> name,
- LookupResult* result) {
+void JSObject::LookupOwnRealNamedProperty(Handle<Name> name,
+ LookupResult* result) {
DisallowHeapAllocation no_gc;
if (IsJSGlobalProxy()) {
Object* proto = GetPrototype();
if (proto->IsNull()) return result->NotFound();
ASSERT(proto->IsJSGlobalObject());
- return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
+ return JSObject::cast(proto)->LookupOwnRealNamedProperty(name, result);
}
if (HasFastProperties()) {
map()->LookupDescriptor(this, *name, result);
// A property or a map transition was found. We return all of these result
- // types because LocalLookupRealNamedProperty is used when setting
+ // types because LookupOwnRealNamedProperty is used when setting
// properties where map transitions are handled.
ASSERT(!result->IsFound() ||
(result->holder() == this && result->IsFastPropertyType()));
@@ -3572,7 +3572,7 @@
void JSObject::LookupRealNamedProperty(Handle<Name> name,
LookupResult* result) {
DisallowHeapAllocation no_gc;
- LocalLookupRealNamedProperty(name, result);
+ LookupOwnRealNamedProperty(name, result);
if (result->IsFound()) return;
LookupRealNamedPropertyInPrototypes(name, result);
@@ -3590,7 +3590,7 @@
if (pt->IsJSProxy()) {
return result->HandlerResult(JSProxy::cast(pt));
}
- JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
+ JSObject::cast(pt)->LookupOwnRealNamedProperty(name, result);
ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
if (result->IsFound()) return;
}
@@ -4153,10 +4153,10 @@
}
-static void ConvertAndSetLocalProperty(LookupResult* lookup,
- Handle<Name> name,
- Handle<Object> value,
- PropertyAttributes attributes) {
+static void ConvertAndSetOwnProperty(LookupResult* lookup,
+ Handle<Name> name,
+ Handle<Object> value,
+ PropertyAttributes attributes) {
Handle<JSObject> object(lookup->holder());
if (object->TooManyFastProperties()) {
JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
@@ -4191,7 +4191,7 @@
if (value->IsUninitialized()) return;
SetPropertyToField(lookup, value);
} else {
- ConvertAndSetLocalProperty(lookup, name, value, attributes);
+ ConvertAndSetOwnProperty(lookup, name, value, attributes);
}
}
@@ -4314,7 +4314,7 @@
EnqueueChangeRecord(object, "add", name, old_value);
} else {
LookupResult new_lookup(isolate);
- object->LocalLookup(name, &new_lookup, true);
+ object->LookupOwn(name, &new_lookup, true);
if (new_lookup.IsDataProperty()) {
Handle<Object> new_value =
Object::GetPropertyOrElement(object, name).ToHandleChecked();
@@ -4329,7 +4329,7 @@
}
-// Set a real local property, even if it is READ_ONLY. If the property is not
+// Set a real own property, even if it is READ_ONLY. If the property is not
// present, add it with attributes NONE. This code is an exact clone of
// SetProperty, with the check for IsReadOnly and the check for a
// callback setter removed. The two lines looking up the LookupResult
@@ -4338,7 +4338,7 @@
// Note that this method cannot be used to set the prototype of a function
// because ConvertDescriptorToField() which is called in "case CALLBACKS:"
// doesn't handle function prototypes correctly.
-MaybeHandle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
+MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
Handle<JSObject> object,
Handle<Name> name,
Handle<Object> value,
@@ -4354,7 +4354,7 @@
AssertNoContextChange ncc(isolate);
LookupResult lookup(isolate);
- object->LocalLookup(name, &lookup, true);
+ object->LookupOwn(name, &lookup, true);
if (!lookup.IsFound()) {
object->map()->LookupTransition(*object, *name, &lookup);
}
@@ -4371,13 +4371,13 @@
Handle<Object> proto(object->GetPrototype(), isolate);
if (proto->IsNull()) return value;
ASSERT(proto->IsJSGlobalObject());
- return SetLocalPropertyIgnoreAttributes(Handle<JSObject>::cast(proto),
+ return SetOwnPropertyIgnoreAttributes(Handle<JSObject>::cast(proto),
name, value, attributes, value_type, mode, extensibility_check);
}
if (lookup.IsInterceptor() ||
(lookup.IsDescriptorOrDictionary() && lookup.type() == CALLBACKS)) {
- object->LocalLookupRealNamedProperty(name, &lookup);
+ object->LookupOwnRealNamedProperty(name, &lookup);
}
// Check for accessor in prototype chain removed here in clone.
@@ -4425,7 +4425,7 @@
}
break;
case CALLBACKS:
- ConvertAndSetLocalProperty(&lookup, name, value, attributes);
+ ConvertAndSetOwnProperty(&lookup, name, value, attributes);
break;
case NONEXISTENT:
case HANDLER:
@@ -4441,7 +4441,7 @@
EnqueueChangeRecord(object, "reconfigure", name, old_value);
} else {
LookupResult new_lookup(isolate);
- object->LocalLookup(name, &new_lookup, true);
+ object->LookupOwn(name, &new_lookup, true);
bool value_changed = false;
if (new_lookup.IsDataProperty()) {
Handle<Object> new_value =
@@ -4466,10 +4466,10 @@
Handle<JSObject> receiver,
Handle<Name> name,
bool continue_search) {
- // Check local property, ignore interceptor.
+ // Check own property, ignore interceptor.
Isolate* isolate = object->GetIsolate();
LookupResult result(isolate);
- object->LocalLookupRealNamedProperty(name, &result);
+ object->LookupOwnRealNamedProperty(name, &result);
if (result.IsFound()) return result.GetAttributes();
if (continue_search) {
@@ -4583,16 +4583,16 @@
}
-PropertyAttributes JSReceiver::GetLocalPropertyAttribute(
+PropertyAttributes JSReceiver::GetOwnPropertyAttribute(
Handle<JSReceiver> object, Handle<Name> name) {
// Check whether the name is an array index.
uint32_t index = 0;
if (object->IsJSObject() && name->AsArrayIndex(&index)) {
- return GetLocalElementAttribute(object, index);
+ return GetOwnElementAttribute(object, index);
}
// Named property.
LookupResult lookup(object->GetIsolate());
- object->LocalLookup(name, &lookup, true);
+ object->LookupOwn(name, &lookup, true);
return GetPropertyAttributeForResult(object, object, &lookup, name, false);
}
@@ -5299,7 +5299,7 @@
} else {
Isolate* isolate = GetIsolate();
LookupResult result(isolate);
- LocalLookupRealNamedProperty(isolate->factory()->hidden_string(), &result);
+ LookupOwnRealNamedProperty(isolate->factory()->hidden_string(), &result);
if (result.IsFound()) {
ASSERT(result.IsNormal());
ASSERT(result.holder() == this);
@@ -5331,7 +5331,7 @@
inline_value);
}
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
object,
isolate->factory()->hidden_string(),
hashtable,
@@ -5369,13 +5369,13 @@
}
}
- SetLocalPropertyIgnoreAttributes(object,
- isolate->factory()->hidden_string(),
- value,
- DONT_ENUM,
- OPTIMAL_REPRESENTATION,
- ALLOW_AS_CONSTANT,
- OMIT_EXTENSIBILITY_CHECK).Assert();
+ SetOwnPropertyIgnoreAttributes(object,
+ isolate->factory()->hidden_string(),
+ value,
+ DONT_ENUM,
+ OPTIMAL_REPRESENTATION,
+ ALLOW_AS_CONSTANT,
+ OMIT_EXTENSIBILITY_CHECK).Assert();
return object;
}
@@ -5383,10 +5383,10 @@
Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object,
Handle<Name> name,
DeleteMode mode) {
- // Check local property, ignore interceptor.
+ // Check own property, ignore interceptor.
Isolate* isolate = object->GetIsolate();
LookupResult result(isolate);
- object->LocalLookupRealNamedProperty(name, &result);
+ object->LookupOwnRealNamedProperty(name, &result);
if (!result.IsFound()) return isolate->factory()->true_value();
// Normalize object if needed.
@@ -5499,9 +5499,9 @@
Handle<Object> old_value;
bool should_enqueue_change_record = false;
if (object->map()->is_observed()) {
- should_enqueue_change_record = HasLocalElement(object, index);
+ should_enqueue_change_record = HasOwnElement(object, index);
if (should_enqueue_change_record) {
- if (!GetLocalElementAccessorPair(object, index).is_null()) {
+ if (!GetOwnElementAccessorPair(object, index).is_null()) {
old_value = Handle<Object>::cast(factory->the_hole_value());
} else {
old_value = Object::GetElement(
@@ -5520,7 +5520,7 @@
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
- if (should_enqueue_change_record && !HasLocalElement(object, index)) {
+ if (should_enqueue_change_record && !HasOwnElement(object, index)) {
Handle<String> name = factory->Uint32ToString(index);
EnqueueChangeRecord(object, "delete", name, old_value);
}
@@ -5558,7 +5558,7 @@
}
LookupResult lookup(isolate);
- object->LocalLookup(name, &lookup, true);
+ object->LookupOwn(name, &lookup, true);
if (!lookup.IsFound()) return isolate->factory()->true_value();
// Ignore attributes if forcing a deletion.
if (lookup.IsDontDelete() && mode != FORCE_DELETION) {
@@ -5599,7 +5599,7 @@
result = DeleteNormalizedProperty(object, name, mode);
}
- if (is_observed && !HasLocalProperty(object, name)) {
+ if (is_observed && !HasOwnProperty(object, name)) {
EnqueueChangeRecord(object, "delete", name, old_value);
}
@@ -6053,7 +6053,7 @@
if (!shallow) {
HandleScope scope(isolate);
- // Deep copy local properties.
+ // Deep copy own properties.
if (copy->HasFastProperties()) {
Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
int limit = copy->map()->NumberOfOwnDescriptors();
@@ -6077,13 +6077,13 @@
}
} else {
Handle<FixedArray> names =
- isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties());
- copy->GetLocalPropertyNames(*names, 0);
+ isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties());
+ copy->GetOwnPropertyNames(*names, 0);
for (int i = 0; i < names->length(); i++) {
ASSERT(names->get(i)->IsString());
Handle<String> key_string(String::cast(names->get(i)));
PropertyAttributes attributes =
- JSReceiver::GetLocalPropertyAttribute(copy, key_string);
+ JSReceiver::GetOwnPropertyAttribute(copy, key_string);
// Only deep copy fields from the object literal expression.
// In particular, don't try to copy the length attribute of
// an array.
@@ -6105,7 +6105,7 @@
}
}
- // Deep copy local elements.
+ // Deep copy own elements.
// Pixel elements cannot be created using an object literal.
ASSERT(!copy->HasExternalArrayElements());
switch (kind) {
@@ -6317,7 +6317,7 @@
}
-void JSReceiver::LocalLookup(
+void JSReceiver::LookupOwn(
Handle<Name> name, LookupResult* result, bool search_hidden_prototypes) {
DisallowHeapAllocation no_gc;
ASSERT(name->IsName());
@@ -6326,7 +6326,7 @@
Object* proto = GetPrototype();
if (proto->IsNull()) return result->NotFound();
ASSERT(proto->IsJSGlobalObject());
- return JSReceiver::cast(proto)->LocalLookup(
+ return JSReceiver::cast(proto)->LookupOwn(
name, result, search_hidden_prototypes);
}
@@ -6350,14 +6350,14 @@
return;
}
- js_object->LocalLookupRealNamedProperty(name, result);
+ js_object->LookupOwnRealNamedProperty(name, result);
if (result->IsFound() || !search_hidden_prototypes) return;
Object* proto = js_object->GetPrototype();
if (!proto->IsJSReceiver()) return;
JSReceiver* receiver = JSReceiver::cast(proto);
if (receiver->map()->is_hidden_prototype()) {
- receiver->LocalLookup(name, result, search_hidden_prototypes);
+ receiver->LookupOwn(name, result, search_hidden_prototypes);
}
}
@@ -6369,7 +6369,7 @@
for (Object* current = this;
current != *null_value;
current = JSObject::cast(current)->GetPrototype()) {
- JSReceiver::cast(current)->LocalLookup(name, result, false);
+ JSReceiver::cast(current)->LookupOwn(name, result, false);
if (result->IsFound()) return;
}
result->NotFound();
@@ -6383,7 +6383,7 @@
for (Object* current = this;
current != *null_value && current->IsJSObject();
current = JSObject::cast(current)->GetPrototype()) {
- JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
+ JSObject::cast(current)->LookupOwnRealNamedProperty(name, result);
if (result->IsPropertyCallbacks()) return;
}
result->NotFound();
@@ -6623,9 +6623,9 @@
ASSERT(ContainsOnlyValidKeys(content));
}
- // If we only want local properties we bail out after the first
+ // If we only want own properties we bail out after the first
// iteration.
- if (type == LOCAL_ONLY) break;
+ if (type == OWN_ONLY) break;
}
return content;
}
@@ -6730,7 +6730,7 @@
Handle<Name> name) {
Isolate* isolate = object->GetIsolate();
LookupResult result(isolate);
- object->LocalLookupRealNamedProperty(name, &result);
+ object->LookupOwnRealNamedProperty(name, &result);
if (result.IsPropertyCallbacks()) {
// Note that the result can actually have IsDontDelete() == true when we
// e.g. have to fall back to the slow case while adding a setter after
@@ -6937,14 +6937,14 @@
bool preexists = false;
if (is_observed) {
if (is_element) {
- preexists = HasLocalElement(object, index);
- if (preexists && GetLocalElementAccessorPair(object, index).is_null()) {
+ preexists = HasOwnElement(object, index);
+ if (preexists && GetOwnElementAccessorPair(object, index).is_null()) {
old_value =
Object::GetElement(isolate, object, index).ToHandleChecked();
}
} else {
LookupResult lookup(isolate);
- object->LocalLookup(name, &lookup, true);
+ object->LookupOwn(name, &lookup, true);
preexists = lookup.IsProperty();
if (preexists && lookup.IsDataProperty()) {
old_value =
@@ -7005,7 +7005,7 @@
ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined());
Isolate* isolate = object->GetIsolate();
LookupResult result(isolate);
- object->LocalLookup(name, &result);
+ object->LookupOwn(name, &result);
if (result.IsFound() && !result.IsPropertyCallbacks()) {
return false;
@@ -7140,7 +7140,7 @@
} else {
// Lookup the name.
LookupResult result(isolate);
- object->LocalLookup(name, &result, true);
+ object->LookupOwn(name, &result, true);
// ES5 forbids turning a property into an accessor if it's not
// configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
if (result.IsFound() && (result.IsReadOnly() || result.IsDontDelete())) {
@@ -7196,7 +7196,7 @@
!obj->IsNull();
obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) {
LookupResult result(isolate);
- JSReceiver::cast(*obj)->LocalLookup(name, &result);
+ JSReceiver::cast(*obj)->LookupOwn(name, &result);
if (result.IsFound()) {
if (result.IsReadOnly()) return isolate->factory()->undefined_value();
if (result.IsPropertyCallbacks()) {
@@ -8826,7 +8826,7 @@
}
-// Archive statics that are thread local.
+// Archive statics that are thread-local.
char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
*reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
isolate->set_relocatable_top(NULL);
@@ -8834,7 +8834,7 @@
}
-// Restore statics that are thread local.
+// Restore statics that are thread-local.
char* Relocatable::RestoreState(Isolate* isolate, char* from) {
isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
return from + ArchiveSpacePerThread();
@@ -10706,9 +10706,7 @@
if (code()->kind() == Code::FUNCTION) {
code()->set_optimizable(false);
}
- PROFILE(GetIsolate(),
- LogExistingFunction(Handle<SharedFunctionInfo>(this),
- Handle<Code>(code())));
+ PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
if (FLAG_trace_opt) {
PrintF("[disabled optimization for ");
ShortPrint();
@@ -10739,7 +10737,7 @@
// No tracking during the snapshot construction phase.
Isolate* isolate = GetIsolate();
- if (Serializer::enabled(isolate)) return;
+ if (isolate->serializer_enabled()) return;
if (map->unused_property_fields() == 0) return;
@@ -11247,13 +11245,30 @@
void SharedFunctionInfo::ClearTypeFeedbackInfo() {
FixedArray* vector = feedback_vector();
Heap* heap = GetHeap();
- for (int i = 0; i < vector->length(); i++) {
+ int length = vector->length();
+
+ for (int i = 0; i < length; i++) {
Object* obj = vector->get(i);
- if (!obj->IsAllocationSite()) {
- vector->set(
- i,
- TypeFeedbackInfo::RawUninitializedSentinel(heap),
- SKIP_WRITE_BARRIER);
+ if (obj->IsHeapObject()) {
+ InstanceType instance_type =
+ HeapObject::cast(obj)->map()->instance_type();
+ switch (instance_type) {
+ case ALLOCATION_SITE_TYPE:
+ // AllocationSites are not cleared because they do not store
+ // information that leaks.
+ break;
+ case JS_FUNCTION_TYPE:
+ // No need to clear the native context array function.
+ if (obj == JSFunction::cast(obj)->context()->native_context()->
+ get(Context::ARRAY_FUNCTION_INDEX)) {
+ break;
+ }
+ // Fall through...
+
+ default:
+ vector->set(i, TypeFeedbackInfo::RawUninitializedSentinel(heap),
+ SKIP_WRITE_BARRIER);
+ }
}
}
}
@@ -11918,11 +11933,11 @@
List<Handle<Object> >* old_values,
List<uint32_t>* indices) {
PropertyAttributes attributes =
- JSReceiver::GetLocalElementAttribute(object, index);
+ JSReceiver::GetOwnElementAttribute(object, index);
ASSERT(attributes != ABSENT);
if (attributes == DONT_DELETE) return false;
Handle<Object> value;
- if (!JSObject::GetLocalElementAccessorPair(object, index).is_null()) {
+ if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) {
value = Handle<Object>::cast(isolate->factory()->the_hole_value());
} else {
value = Object::GetElement(isolate, object, index).ToHandleChecked();
@@ -11998,7 +12013,7 @@
CHECK(new_length_handle->ToArrayIndex(&new_length));
static const PropertyAttributes kNoAttrFilter = NONE;
- int num_elements = array->NumberOfLocalElements(kNoAttrFilter);
+ int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
if (num_elements > 0) {
if (old_length == static_cast<uint32_t>(num_elements)) {
// Simple case for arrays without holes.
@@ -12010,7 +12025,7 @@
// TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
// the to-be-removed indices twice.
Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
- array->GetLocalElementKeys(*keys, kNoAttrFilter);
+ array->GetOwnElementKeys(*keys, kNoAttrFilter);
while (num_elements-- > 0) {
uint32_t index = NumberToUint32(keys->get(num_elements));
if (index < new_length) break;
@@ -12503,17 +12518,17 @@
}
-MaybeHandle<AccessorPair> JSObject::GetLocalPropertyAccessorPair(
+MaybeHandle<AccessorPair> JSObject::GetOwnPropertyAccessorPair(
Handle<JSObject> object,
Handle<Name> name) {
uint32_t index = 0;
if (name->AsArrayIndex(&index)) {
- return GetLocalElementAccessorPair(object, index);
+ return GetOwnElementAccessorPair(object, index);
}
Isolate* isolate = object->GetIsolate();
LookupResult lookup(isolate);
- object->LocalLookupRealNamedProperty(name, &lookup);
+ object->LookupOwnRealNamedProperty(name, &lookup);
if (lookup.IsPropertyCallbacks() &&
lookup.GetCallbackObject()->IsAccessorPair()) {
@@ -12523,14 +12538,14 @@
}
-MaybeHandle<AccessorPair> JSObject::GetLocalElementAccessorPair(
+MaybeHandle<AccessorPair> JSObject::GetOwnElementAccessorPair(
Handle<JSObject> object,
uint32_t index) {
if (object->IsJSGlobalProxy()) {
Handle<Object> proto(object->GetPrototype(), object->GetIsolate());
if (proto->IsNull()) return MaybeHandle<AccessorPair>();
ASSERT(proto->IsJSGlobalObject());
- return GetLocalElementAccessorPair(Handle<JSObject>::cast(proto), index);
+ return GetOwnElementAccessorPair(Handle<JSObject>::cast(proto), index);
}
// Check for lookup interceptor.
@@ -13168,13 +13183,13 @@
}
PropertyAttributes old_attributes =
- JSReceiver::GetLocalElementAttribute(object, index);
+ JSReceiver::GetOwnElementAttribute(object, index);
Handle<Object> old_value = isolate->factory()->the_hole_value();
Handle<Object> old_length_handle;
Handle<Object> new_length_handle;
if (old_attributes != ABSENT) {
- if (GetLocalElementAccessorPair(object, index).is_null()) {
+ if (GetOwnElementAccessorPair(object, index).is_null()) {
old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
}
} else if (object->IsJSArray()) {
@@ -13197,7 +13212,7 @@
Object);
Handle<String> name = isolate->factory()->Uint32ToString(index);
- PropertyAttributes new_attributes = GetLocalElementAttribute(object, index);
+ PropertyAttributes new_attributes = GetOwnElementAttribute(object, index);
if (old_attributes == ABSENT) {
if (object->IsJSArray() &&
!old_length_handle->SameValue(
@@ -13260,6 +13275,14 @@
CheckArrayAbuse(object, "elements write", index, true);
}
}
+ if (object->IsJSArray() && JSArray::WouldChangeReadOnlyLength(
+ Handle<JSArray>::cast(object), index)) {
+ if (strict_mode == SLOPPY) {
+ return value;
+ } else {
+ return JSArray::ReadOnlyLengthError(Handle<JSArray>::cast(object));
+ }
+ }
switch (object->GetElementsKind()) {
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
@@ -13545,6 +13568,41 @@
}
+bool JSArray::IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map) {
+ Isolate* isolate = jsarray_map->GetIsolate();
+ ASSERT(!jsarray_map->is_dictionary_map());
+ LookupResult lookup(isolate);
+ Handle<Name> length_string = isolate->factory()->length_string();
+ jsarray_map->LookupDescriptor(NULL, *length_string, &lookup);
+ return lookup.IsReadOnly();
+}
+
+
+bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
+ uint32_t index) {
+ uint32_t length = 0;
+ CHECK(array->length()->ToArrayIndex(&length));
+ if (length <= index) {
+ Isolate* isolate = array->GetIsolate();
+ LookupResult lookup(isolate);
+ Handle<Name> length_string = isolate->factory()->length_string();
+ array->LookupOwnRealNamedProperty(length_string, &lookup);
+ return lookup.IsReadOnly();
+ }
+ return false;
+}
+
+
+MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
+ Isolate* isolate = array->GetIsolate();
+ Handle<Name> length = isolate->factory()->length_string();
+ Handle<Object> args[2] = { length, array };
+ Handle<Object> error = isolate->factory()->NewTypeError(
+ "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
+ return isolate->Throw<Object>(error);
+}
+
+
MaybeHandle<Object> JSObject::GetElementWithInterceptor(
Handle<JSObject> object,
Handle<Object> receiver,
@@ -13834,10 +13892,10 @@
Handle<Object> receiver,
Handle<Name> name,
PropertyAttributes* attributes) {
- // Check local property in holder, ignore interceptor.
+ // Check own property in holder, ignore interceptor.
Isolate* isolate = object->GetIsolate();
LookupResult lookup(isolate);
- object->LocalLookupRealNamedProperty(name, &lookup);
+ object->LookupOwnRealNamedProperty(name, &lookup);
if (lookup.IsFound()) {
return GetProperty(object, receiver, &lookup, name, attributes);
} else {
@@ -13951,7 +14009,7 @@
}
LookupResult result(isolate);
- object->LocalLookupRealNamedProperty(key, &result);
+ object->LookupOwnRealNamedProperty(key, &result);
return result.IsFound() && !result.IsInterceptor();
}
@@ -13995,12 +14053,12 @@
}
LookupResult result(isolate);
- object->LocalLookupRealNamedProperty(key, &result);
+ object->LookupOwnRealNamedProperty(key, &result);
return result.IsPropertyCallbacks();
}
-int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
+int JSObject::NumberOfOwnProperties(PropertyAttributes filter) {
if (HasFastProperties()) {
Map* map = this->map();
if (filter == NONE) return map->NumberOfOwnDescriptors();
@@ -14127,12 +14185,12 @@
}
-// Fill in the names of local properties into the supplied storage. The main
+// Fill in the names of own properties into the supplied storage. The main
// purpose of this function is to provide reflection information for the object
// mirrors.
-void JSObject::GetLocalPropertyNames(
+void JSObject::GetOwnPropertyNames(
FixedArray* storage, int index, PropertyAttributes filter) {
- ASSERT(storage->length() >= (NumberOfLocalProperties(filter) - index));
+ ASSERT(storage->length() >= (NumberOfOwnProperties(filter) - index));
if (HasFastProperties()) {
int real_size = map()->NumberOfOwnDescriptors();
DescriptorArray* descs = map()->instance_descriptors();
@@ -14151,8 +14209,8 @@
}
-int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
- return GetLocalElementKeys(NULL, filter);
+int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
+ return GetOwnElementKeys(NULL, filter);
}
@@ -14166,12 +14224,12 @@
if (length == 0) return 0;
}
// Compute the number of enumerable elements.
- return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
+ return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
}
-int JSObject::GetLocalElementKeys(FixedArray* storage,
- PropertyAttributes filter) {
+int JSObject::GetOwnElementKeys(FixedArray* storage,
+ PropertyAttributes filter) {
int counter = 0;
switch (GetElementsKind()) {
case FAST_SMI_ELEMENTS:
@@ -14196,7 +14254,7 @@
case FAST_HOLEY_DOUBLE_ELEMENTS: {
int length = IsJSArray() ?
Smi::cast(JSArray::cast(this)->length())->value() :
- FixedDoubleArray::cast(elements())->length();
+ FixedArrayBase::cast(elements())->length();
for (int i = 0; i < length; i++) {
if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
if (storage != NULL) {
@@ -14297,8 +14355,7 @@
int JSObject::GetEnumElementKeys(FixedArray* storage) {
- return GetLocalElementKeys(storage,
- static_cast<PropertyAttributes>(DONT_ENUM));
+ return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
}
@@ -16991,7 +17048,7 @@
// Since the stamp is not NaN, the value is also not NaN.
int64_t local_time_ms =
date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
- SetLocalFields(local_time_ms, date_cache);
+ SetCachedFields(local_time_ms, date_cache);
}
switch (index) {
case kYear: return year();
@@ -17084,7 +17141,7 @@
}
-void JSDate::SetLocalFields(int64_t local_time_ms, DateCache* date_cache) {
+void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
int days = DateCache::DaysFromTime(local_time_ms);
int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
int year, month, day;
diff --git a/src/objects.h b/src/objects.h
index 944efb9..47fea39 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1922,9 +1922,9 @@
// Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6.
static inline bool HasProperty(Handle<JSReceiver> object, Handle<Name> name);
- static inline bool HasLocalProperty(Handle<JSReceiver>, Handle<Name> name);
+ static inline bool HasOwnProperty(Handle<JSReceiver>, Handle<Name> name);
static inline bool HasElement(Handle<JSReceiver> object, uint32_t index);
- static inline bool HasLocalElement(Handle<JSReceiver> object, uint32_t index);
+ static inline bool HasOwnElement(Handle<JSReceiver> object, uint32_t index);
// Implementation of [[Delete]], ECMA-262 5th edition, section 8.12.7.
MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty(
@@ -1953,14 +1953,14 @@
Handle<JSReceiver> object,
Handle<JSReceiver> receiver,
Handle<Name> name);
- static PropertyAttributes GetLocalPropertyAttribute(
+ static PropertyAttributes GetOwnPropertyAttribute(
Handle<JSReceiver> object,
Handle<Name> name);
static inline PropertyAttributes GetElementAttribute(
Handle<JSReceiver> object,
uint32_t index);
- static inline PropertyAttributes GetLocalElementAttribute(
+ static inline PropertyAttributes GetOwnElementAttribute(
Handle<JSReceiver> object,
uint32_t index);
@@ -1981,11 +1981,11 @@
// Lookup a property. If found, the result is valid and has
// detailed information.
- void LocalLookup(Handle<Name> name, LookupResult* result,
- bool search_hidden_prototypes = false);
+ void LookupOwn(Handle<Name> name, LookupResult* result,
+ bool search_hidden_prototypes = false);
void Lookup(Handle<Name> name, LookupResult* result);
- enum KeyCollectionType { LOCAL_ONLY, INCLUDE_PROTOS };
+ enum KeyCollectionType { OWN_ONLY, INCLUDE_PROTOS };
// Computes the enumerable keys for a JSObject. Used for implementing
// "for (n in object) { }".
@@ -2157,7 +2157,7 @@
StrictMode strict_mode,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
- MUST_USE_RESULT static MaybeHandle<Object> SetLocalPropertyIgnoreAttributes(
+ MUST_USE_RESULT static MaybeHandle<Object> SetOwnPropertyIgnoreAttributes(
Handle<JSObject> object,
Handle<Name> key,
Handle<Object> value,
@@ -2273,8 +2273,8 @@
// Accessors for hidden properties object.
//
- // Hidden properties are not local properties of the object itself.
- // Instead they are stored in an auxiliary structure kept as a local
+ // Hidden properties are not own properties of the object itself.
+ // Instead they are stored in an auxiliary structure kept as an own
// property with a special name Heap::hidden_string(). But if the
// receiver is a JSGlobalProxy then the auxiliary object is a property
// of its prototype, and if it's a detached proxy, then you can't have
@@ -2344,10 +2344,10 @@
}
// These methods do not perform access checks!
- MUST_USE_RESULT static MaybeHandle<AccessorPair> GetLocalPropertyAccessorPair(
+ MUST_USE_RESULT static MaybeHandle<AccessorPair> GetOwnPropertyAccessorPair(
Handle<JSObject> object,
Handle<Name> name);
- MUST_USE_RESULT static MaybeHandle<AccessorPair> GetLocalElementAccessorPair(
+ MUST_USE_RESULT static MaybeHandle<AccessorPair> GetOwnElementAccessorPair(
Handle<JSObject> object,
uint32_t index);
@@ -2432,7 +2432,7 @@
inline void SetInternalField(int index, Smi* value);
// The following lookup functions skip interceptors.
- void LocalLookupRealNamedProperty(Handle<Name> name, LookupResult* result);
+ void LookupOwnRealNamedProperty(Handle<Name> name, LookupResult* result);
void LookupRealNamedProperty(Handle<Name> name, LookupResult* result);
void LookupRealNamedPropertyInPrototypes(Handle<Name> name,
LookupResult* result);
@@ -2440,20 +2440,20 @@
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
- int NumberOfLocalProperties(PropertyAttributes filter = NONE);
+ int NumberOfOwnProperties(PropertyAttributes filter = NONE);
// Fill in details for properties into storage starting at the specified
// index.
- void GetLocalPropertyNames(
+ void GetOwnPropertyNames(
FixedArray* storage, int index, PropertyAttributes filter = NONE);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
- int NumberOfLocalElements(PropertyAttributes filter);
+ int NumberOfOwnElements(PropertyAttributes filter);
// Returns the number of enumerable elements (ignoring interceptors).
int NumberOfEnumElements();
// Returns the number of elements on this object filtering out elements
// with the specified attributes (ignoring interceptors).
- int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter);
+ int GetOwnElementKeys(FixedArray* storage, PropertyAttributes filter);
// Count and fill in the enumerable elements into storage.
// (storage->length() == NumberOfEnumElements()).
// If storage is NULL, will count the elements without adding
@@ -2468,7 +2468,7 @@
static void TransitionElementsKind(Handle<JSObject> object,
ElementsKind to_kind);
- // TODO(mstarzinger): Both public because of ConvertAnsSetLocalProperty().
+ // TODO(mstarzinger): Both public because of ConvertAndSetOwnProperty().
static void MigrateToMap(Handle<JSObject> object, Handle<Map> new_map);
static void GeneralizeFieldRepresentation(Handle<JSObject> object,
int modify_index,
@@ -7495,6 +7495,8 @@
// cannot be resumed.
inline int continuation();
inline void set_continuation(int continuation);
+ inline bool is_closed();
+ inline bool is_executing();
inline bool is_suspended();
// [operand_stack]: Saved operand stack.
@@ -7920,7 +7922,7 @@
// [sec]: caches seconds. Either undefined, smi, or NaN.
DECL_ACCESSORS(sec, Object)
// [cache stamp]: sample of the date cache stamp at the
- // moment when local fields were cached.
+ // moment when chached fields were cached.
DECL_ACCESSORS(cache_stamp, Object)
// Casting.
@@ -7984,7 +7986,7 @@
Object* GetUTCField(FieldIndex index, double value, DateCache* date_cache);
// Computes and caches the cacheable fields of the date.
- inline void SetLocalFields(int64_t local_time_ms, DateCache* date_cache);
+ inline void SetCachedFields(int64_t local_time_ms, DateCache* date_cache);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSDate);
@@ -10336,6 +10338,10 @@
uint32_t index,
Handle<Object> value);
+ static bool IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map);
+ static bool WouldChangeReadOnlyLength(Handle<JSArray> array, uint32_t index);
+ static MaybeHandle<Object> ReadOnlyLengthError(Handle<JSArray> array);
+
// Initialize the array with the given capacity. The function may
// fail due to out-of-memory situations, but only if the requested
// capacity is non-zero.
@@ -10569,7 +10575,7 @@
// the request is ignored.
//
// If the accessor in the prototype has the READ_ONLY property attribute, then
-// a new value is added to the local object when the property is set.
+// a new value is added to the derived object when the property is set.
// This shadows the accessor in the prototype.
class ExecutableAccessorInfo: public AccessorInfo {
public:
diff --git a/src/parser.cc b/src/parser.cc
index 5efcba6..572b0f4 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1267,7 +1267,7 @@
Interface* interface = scope->interface();
for (Interface::Iterator it = interface->iterator();
!it.done(); it.Advance()) {
- if (scope->LocalLookup(it.name()) == NULL) {
+ if (scope->LookupLocal(it.name()) == NULL) {
ParserTraits::ReportMessage("module_export_undefined", it.name());
*ok = false;
return NULL;
@@ -1679,7 +1679,7 @@
// global scope.
var = declaration_scope->is_global_scope()
? declaration_scope->Lookup(name)
- : declaration_scope->LocalLookup(name);
+ : declaration_scope->LookupLocal(name);
if (var == NULL) {
// Declare the name.
var = declaration_scope->DeclareLocal(
diff --git a/src/promise.js b/src/promise.js
index d202f28..f7d6307 100644
--- a/src/promise.js
+++ b/src/promise.js
@@ -9,28 +9,18 @@
// var $Object = global.Object
// var $WeakMap = global.WeakMap
+// For bootstrapper.
-var $Promise = function Promise(resolver) {
- if (resolver === promiseRaw) return;
- if (!%_IsConstructCall()) throw MakeTypeError('not_a_promise', [this]);
- if (!IS_SPEC_FUNCTION(resolver))
- throw MakeTypeError('resolver_not_a_function', [resolver]);
- var promise = PromiseInit(this);
- try {
- %DebugPromiseHandlePrologue(function() { return promise });
- resolver(function(x) { PromiseResolve(promise, x) },
- function(r) { PromiseReject(promise, r) });
- } catch (e) {
- PromiseReject(promise, e);
- } finally {
- %DebugPromiseHandleEpilogue();
- }
-}
+var IsPromise;
+var PromiseCreate;
+var PromiseResolve;
+var PromiseReject;
+var PromiseChain;
+var PromiseCatch;
-
-//-------------------------------------------------------------------
-
-// Core functionality.
+// mirror-debugger.js currently uses builtins.promiseStatus. It would be nice
+// if we could move these property names into the closure below.
+// TODO(jkummerow/rossberg/yangguo): Find a better solution.
// Status values: 0 = pending, +1 = resolved, -1 = rejected
var promiseStatus = GLOBAL_PRIVATE("Promise#status");
@@ -39,250 +29,274 @@
var promiseOnReject = GLOBAL_PRIVATE("Promise#onReject");
var promiseRaw = GLOBAL_PRIVATE("Promise#raw");
-function IsPromise(x) {
- return IS_SPEC_OBJECT(x) && %HasLocalProperty(x, promiseStatus);
-}
+(function() {
-function PromiseSet(promise, status, value, onResolve, onReject) {
- SET_PRIVATE(promise, promiseStatus, status);
- SET_PRIVATE(promise, promiseValue, value);
- SET_PRIVATE(promise, promiseOnResolve, onResolve);
- SET_PRIVATE(promise, promiseOnReject, onReject);
- return promise;
-}
-
-function PromiseInit(promise) {
- return PromiseSet(promise, 0, UNDEFINED, new InternalArray, new InternalArray)
-}
-
-function PromiseDone(promise, status, value, promiseQueue) {
- if (GET_PRIVATE(promise, promiseStatus) === 0) {
- PromiseEnqueue(value, GET_PRIVATE(promise, promiseQueue));
- PromiseSet(promise, status, value);
- }
-}
-
-function PromiseResolve(promise, x) {
- PromiseDone(promise, +1, x, promiseOnResolve)
-}
-
-function PromiseReject(promise, r) {
- PromiseDone(promise, -1, r, promiseOnReject)
-}
-
-
-// For API.
-
-function PromiseNopResolver() {}
-
-function PromiseCreate() {
- return new $Promise(PromiseNopResolver)
-}
-
-
-// Convenience.
-
-function PromiseDeferred() {
- if (this === $Promise) {
- // Optimized case, avoid extra closure.
- var promise = PromiseInit(new $Promise(promiseRaw));
- return {
- promise: promise,
- resolve: function(x) { PromiseResolve(promise, x) },
- reject: function(r) { PromiseReject(promise, r) }
- };
- } else {
- var result = {};
- result.promise = new this(function(resolve, reject) {
- result.resolve = resolve;
- result.reject = reject;
- })
- return result;
- }
-}
-
-function PromiseResolved(x) {
- if (this === $Promise) {
- // Optimized case, avoid extra closure.
- return PromiseSet(new $Promise(promiseRaw), +1, x);
- } else {
- return new this(function(resolve, reject) { resolve(x) });
- }
-}
-
-function PromiseRejected(r) {
- if (this === $Promise) {
- // Optimized case, avoid extra closure.
- return PromiseSet(new $Promise(promiseRaw), -1, r);
- } else {
- return new this(function(resolve, reject) { reject(r) });
- }
-}
-
-
-// Simple chaining.
-
-function PromiseIdResolveHandler(x) { return x }
-function PromiseIdRejectHandler(r) { throw r }
-
-function PromiseChain(onResolve, onReject) { // a.k.a. flatMap
- onResolve = IS_UNDEFINED(onResolve) ? PromiseIdResolveHandler : onResolve;
- onReject = IS_UNDEFINED(onReject) ? PromiseIdRejectHandler : onReject;
- var deferred = %_CallFunction(this.constructor, PromiseDeferred);
- switch (GET_PRIVATE(this, promiseStatus)) {
- case UNDEFINED:
- throw MakeTypeError('not_a_promise', [this]);
- case 0: // Pending
- GET_PRIVATE(this, promiseOnResolve).push(onResolve, deferred);
- GET_PRIVATE(this, promiseOnReject).push(onReject, deferred);
- break;
- case +1: // Resolved
- PromiseEnqueue(GET_PRIVATE(this, promiseValue), [onResolve, deferred]);
- break;
- case -1: // Rejected
- PromiseEnqueue(GET_PRIVATE(this, promiseValue), [onReject, deferred]);
- break;
- }
- return deferred.promise;
-}
-
-function PromiseCatch(onReject) {
- return this.then(UNDEFINED, onReject);
-}
-
-function PromiseEnqueue(value, tasks) {
- %EnqueueMicrotask(function() {
- for (var i = 0; i < tasks.length; i += 2) {
- PromiseHandle(value, tasks[i], tasks[i + 1])
- }
- });
-}
-
-function PromiseHandle(value, handler, deferred) {
- try {
- %DebugPromiseHandlePrologue(
- function() {
- var queue = GET_PRIVATE(deferred.promise, promiseOnReject);
- return (queue && queue.length == 0) ? deferred.promise : UNDEFINED;
- });
- var result = handler(value);
- if (result === deferred.promise)
- throw MakeTypeError('promise_cyclic', [result]);
- else if (IsPromise(result))
- %_CallFunction(result, deferred.resolve, deferred.reject, PromiseChain);
- else
- deferred.resolve(result);
- } catch (exception) {
+ var $Promise = function Promise(resolver) {
+ if (resolver === promiseRaw) return;
+ if (!%_IsConstructCall()) throw MakeTypeError('not_a_promise', [this]);
+ if (!IS_SPEC_FUNCTION(resolver))
+ throw MakeTypeError('resolver_not_a_function', [resolver]);
+ var promise = PromiseInit(this);
try {
- %DebugPromiseHandlePrologue(function() { return deferred.promise });
- deferred.reject(exception);
- } catch (e) { } finally {
+ %DebugPromiseHandlePrologue(function() { return promise });
+ resolver(function(x) { PromiseResolve(promise, x) },
+ function(r) { PromiseReject(promise, r) });
+ } catch (e) {
+ PromiseReject(promise, e);
+ } finally {
%DebugPromiseHandleEpilogue();
}
- } finally {
- %DebugPromiseHandleEpilogue();
}
-}
+ // Core functionality.
-// Multi-unwrapped chaining with thenable coercion.
+ function PromiseSet(promise, status, value, onResolve, onReject) {
+ SET_PRIVATE(promise, promiseStatus, status);
+ SET_PRIVATE(promise, promiseValue, value);
+ SET_PRIVATE(promise, promiseOnResolve, onResolve);
+ SET_PRIVATE(promise, promiseOnReject, onReject);
+ return promise;
+ }
-function PromiseThen(onResolve, onReject) {
- onResolve = IS_SPEC_FUNCTION(onResolve) ? onResolve : PromiseIdResolveHandler;
- onReject = IS_SPEC_FUNCTION(onReject) ? onReject : PromiseIdRejectHandler;
- var that = this;
- var constructor = this.constructor;
- return %_CallFunction(
- this,
- function(x) {
- x = PromiseCoerce(constructor, x);
- return x === that ? onReject(MakeTypeError('promise_cyclic', [x])) :
- IsPromise(x) ? x.then(onResolve, onReject) : onResolve(x);
- },
- onReject,
- PromiseChain
- );
-}
+ function PromiseInit(promise) {
+ return PromiseSet(
+ promise, 0, UNDEFINED, new InternalArray, new InternalArray)
+ }
-function PromiseCoerce(constructor, x) {
- if (!IsPromise(x) && IS_SPEC_OBJECT(x)) {
- var then;
- try {
- then = x.then;
- } catch(r) {
- return %_CallFunction(constructor, r, PromiseRejected);
+ function PromiseDone(promise, status, value, promiseQueue) {
+ if (GET_PRIVATE(promise, promiseStatus) === 0) {
+ PromiseEnqueue(value, GET_PRIVATE(promise, promiseQueue));
+ PromiseSet(promise, status, value);
}
- if (IS_SPEC_FUNCTION(then)) {
- var deferred = %_CallFunction(constructor, PromiseDeferred);
+ }
+
+ function PromiseCoerce(constructor, x) {
+ if (!IsPromise(x) && IS_SPEC_OBJECT(x)) {
+ var then;
try {
- %_CallFunction(x, deferred.resolve, deferred.reject, then);
+ then = x.then;
} catch(r) {
- deferred.reject(r);
+ return %_CallFunction(constructor, r, PromiseRejected);
}
- return deferred.promise;
+ if (IS_SPEC_FUNCTION(then)) {
+ var deferred = %_CallFunction(constructor, PromiseDeferred);
+ try {
+ %_CallFunction(x, deferred.resolve, deferred.reject, then);
+ } catch(r) {
+ deferred.reject(r);
+ }
+ return deferred.promise;
+ }
+ }
+ return x;
+ }
+
+ function PromiseHandle(value, handler, deferred) {
+ try {
+ %DebugPromiseHandlePrologue(
+ function() {
+ var queue = GET_PRIVATE(deferred.promise, promiseOnReject);
+ return (queue && queue.length == 0) ? deferred.promise : UNDEFINED;
+ });
+ var result = handler(value);
+ if (result === deferred.promise)
+ throw MakeTypeError('promise_cyclic', [result]);
+ else if (IsPromise(result))
+ %_CallFunction(result, deferred.resolve, deferred.reject, PromiseChain);
+ else
+ deferred.resolve(result);
+ } catch (exception) {
+ try {
+ %DebugPromiseHandlePrologue(function() { return deferred.promise });
+ deferred.reject(exception);
+ } catch (e) { } finally {
+ %DebugPromiseHandleEpilogue();
+ }
+ } finally {
+ %DebugPromiseHandleEpilogue();
}
}
- return x;
-}
+ function PromiseEnqueue(value, tasks) {
+ %EnqueueMicrotask(function() {
+ for (var i = 0; i < tasks.length; i += 2) {
+ PromiseHandle(value, tasks[i], tasks[i + 1])
+ }
+ });
+ }
-// Combinators.
+ function PromiseIdResolveHandler(x) { return x }
+ function PromiseIdRejectHandler(r) { throw r }
-function PromiseCast(x) {
- // TODO(rossberg): cannot do better until we support @@create.
- return IsPromise(x) ? x : new this(function(resolve) { resolve(x) });
-}
+ function PromiseNopResolver() {}
-function PromiseAll(values) {
- var deferred = %_CallFunction(this, PromiseDeferred);
- var resolutions = [];
- if (!%_IsArray(values)) {
- deferred.reject(MakeTypeError('invalid_argument'));
+ // -------------------------------------------------------------------
+ // Define exported functions.
+
+ // For bootstrapper.
+
+ IsPromise = function IsPromise(x) {
+ return IS_SPEC_OBJECT(x) && HAS_PRIVATE(x, promiseStatus);
+ }
+
+ PromiseCreate = function PromiseCreate() {
+ return new $Promise(PromiseNopResolver)
+ }
+
+ PromiseResolve = function PromiseResolve(promise, x) {
+ PromiseDone(promise, +1, x, promiseOnResolve)
+ }
+
+ PromiseReject = function PromiseReject(promise, r) {
+ PromiseDone(promise, -1, r, promiseOnReject)
+ }
+
+ // Convenience.
+
+ function PromiseDeferred() {
+ if (this === $Promise) {
+ // Optimized case, avoid extra closure.
+ var promise = PromiseInit(new $Promise(promiseRaw));
+ return {
+ promise: promise,
+ resolve: function(x) { PromiseResolve(promise, x) },
+ reject: function(r) { PromiseReject(promise, r) }
+ };
+ } else {
+ var result = {};
+ result.promise = new this(function(resolve, reject) {
+ result.resolve = resolve;
+ result.reject = reject;
+ })
+ return result;
+ }
+ }
+
+ function PromiseResolved(x) {
+ if (this === $Promise) {
+ // Optimized case, avoid extra closure.
+ return PromiseSet(new $Promise(promiseRaw), +1, x);
+ } else {
+ return new this(function(resolve, reject) { resolve(x) });
+ }
+ }
+
+ function PromiseRejected(r) {
+ if (this === $Promise) {
+ // Optimized case, avoid extra closure.
+ return PromiseSet(new $Promise(promiseRaw), -1, r);
+ } else {
+ return new this(function(resolve, reject) { reject(r) });
+ }
+ }
+
+ // Simple chaining.
+
+ PromiseChain = function PromiseChain(onResolve, onReject) { // a.k.a.
+ // flatMap
+ onResolve = IS_UNDEFINED(onResolve) ? PromiseIdResolveHandler : onResolve;
+ onReject = IS_UNDEFINED(onReject) ? PromiseIdRejectHandler : onReject;
+ var deferred = %_CallFunction(this.constructor, PromiseDeferred);
+ switch (GET_PRIVATE(this, promiseStatus)) {
+ case UNDEFINED:
+ throw MakeTypeError('not_a_promise', [this]);
+ case 0: // Pending
+ GET_PRIVATE(this, promiseOnResolve).push(onResolve, deferred);
+ GET_PRIVATE(this, promiseOnReject).push(onReject, deferred);
+ break;
+ case +1: // Resolved
+ PromiseEnqueue(GET_PRIVATE(this, promiseValue), [onResolve, deferred]);
+ break;
+ case -1: // Rejected
+ PromiseEnqueue(GET_PRIVATE(this, promiseValue), [onReject, deferred]);
+ break;
+ }
return deferred.promise;
}
- try {
- var count = values.length;
- if (count === 0) {
- deferred.resolve(resolutions);
- } else {
+
+ PromiseCatch = function PromiseCatch(onReject) {
+ return this.then(UNDEFINED, onReject);
+ }
+
+ // Multi-unwrapped chaining with thenable coercion.
+
+ function PromiseThen(onResolve, onReject) {
+ onResolve = IS_SPEC_FUNCTION(onResolve) ? onResolve
+ : PromiseIdResolveHandler;
+ onReject = IS_SPEC_FUNCTION(onReject) ? onReject
+ : PromiseIdRejectHandler;
+ var that = this;
+ var constructor = this.constructor;
+ return %_CallFunction(
+ this,
+ function(x) {
+ x = PromiseCoerce(constructor, x);
+ return x === that ? onReject(MakeTypeError('promise_cyclic', [x])) :
+ IsPromise(x) ? x.then(onResolve, onReject) : onResolve(x);
+ },
+ onReject,
+ PromiseChain
+ );
+ }
+
+ // Combinators.
+
+ function PromiseCast(x) {
+ // TODO(rossberg): cannot do better until we support @@create.
+ return IsPromise(x) ? x : new this(function(resolve) { resolve(x) });
+ }
+
+ function PromiseAll(values) {
+ var deferred = %_CallFunction(this, PromiseDeferred);
+ var resolutions = [];
+ if (!%_IsArray(values)) {
+ deferred.reject(MakeTypeError('invalid_argument'));
+ return deferred.promise;
+ }
+ try {
+ var count = values.length;
+ if (count === 0) {
+ deferred.resolve(resolutions);
+ } else {
+ for (var i = 0; i < values.length; ++i) {
+ this.resolve(values[i]).then(
+ function(i, x) {
+ resolutions[i] = x;
+ if (--count === 0) deferred.resolve(resolutions);
+ }.bind(UNDEFINED, i), // TODO(rossberg): use let loop once
+ // available
+ function(r) { deferred.reject(r) }
+ );
+ }
+ }
+ } catch (e) {
+ deferred.reject(e)
+ }
+ return deferred.promise;
+ }
+
+ function PromiseOne(values) {
+ var deferred = %_CallFunction(this, PromiseDeferred);
+ if (!%_IsArray(values)) {
+ deferred.reject(MakeTypeError('invalid_argument'));
+ return deferred.promise;
+ }
+ try {
for (var i = 0; i < values.length; ++i) {
this.resolve(values[i]).then(
- function(i, x) {
- resolutions[i] = x;
- if (--count === 0) deferred.resolve(resolutions);
- }.bind(UNDEFINED, i), // TODO(rossberg): use let loop once available
+ function(x) { deferred.resolve(x) },
function(r) { deferred.reject(r) }
);
}
+ } catch (e) {
+ deferred.reject(e)
}
- } catch (e) {
- deferred.reject(e)
- }
- return deferred.promise;
-}
-
-function PromiseOne(values) {
- var deferred = %_CallFunction(this, PromiseDeferred);
- if (!%_IsArray(values)) {
- deferred.reject(MakeTypeError('invalid_argument'));
return deferred.promise;
}
- try {
- for (var i = 0; i < values.length; ++i) {
- this.resolve(values[i]).then(
- function(x) { deferred.resolve(x) },
- function(r) { deferred.reject(r) }
- );
- }
- } catch (e) {
- deferred.reject(e)
- }
- return deferred.promise;
-}
-//-------------------------------------------------------------------
+ // -------------------------------------------------------------------
+ // Install exported functions.
-function SetUpPromise() {
%CheckIsBootstrapping();
%SetProperty(global, 'Promise', $Promise, DONT_ENUM);
InstallFunctions($Promise, DONT_ENUM, [
@@ -298,6 +312,5 @@
"then", PromiseThen,
"catch", PromiseCatch
]);
-}
-SetUpPromise();
+})();
diff --git a/src/runtime.cc b/src/runtime.cc
index 29a3efe..39c3d29 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -277,7 +277,7 @@
} else {
Handle<String> name(String::cast(*key));
ASSERT(!name->AsArrayIndex(&element_index));
- maybe_result = JSObject::SetLocalPropertyIgnoreAttributes(
+ maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(
boilerplate, name, value, NONE,
Object::OPTIMAL_REPRESENTATION, mode);
}
@@ -293,7 +293,7 @@
Vector<char> buffer(arr, ARRAY_SIZE(arr));
const char* str = DoubleToCString(num, buffer);
Handle<String> name = isolate->factory()->NewStringFromAsciiChecked(str);
- maybe_result = JSObject::SetLocalPropertyIgnoreAttributes(
+ maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(
boilerplate, name, value, NONE,
Object::OPTIMAL_REPRESENTATION, mode);
}
@@ -1946,7 +1946,7 @@
Isolate* isolate = obj->GetIsolate();
LookupResult lookup(isolate);
- obj->LocalLookup(name, &lookup, true);
+ obj->LookupOwn(name, &lookup, true);
if (!lookup.IsProperty()) return ACCESS_ABSENT;
Handle<JSObject> holder(lookup.holder(), isolate);
@@ -2013,7 +2013,7 @@
case ACCESS_ABSENT: return factory->undefined_value();
}
- PropertyAttributes attrs = JSReceiver::GetLocalPropertyAttribute(obj, name);
+ PropertyAttributes attrs = JSReceiver::GetOwnPropertyAttribute(obj, name);
if (attrs == ABSENT) {
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return factory->undefined_value();
@@ -2021,7 +2021,7 @@
ASSERT(!isolate->has_scheduled_exception());
Handle<AccessorPair> accessors;
bool has_accessors =
- JSObject::GetLocalPropertyAccessorPair(obj, name).ToHandle(&accessors);
+ JSObject::GetOwnPropertyAccessorPair(obj, name).ToHandle(&accessors);
Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
@@ -2263,9 +2263,9 @@
if (is_var || is_const) {
// Lookup the property in the global object, and don't set the
// value of the variable if the property is already there.
- // Do the lookup locally only, see ES5 erratum.
+ // Do the lookup own properties only, see ES5 erratum.
LookupResult lookup(isolate);
- global->LocalLookup(name, &lookup, true);
+ global->LookupOwn(name, &lookup, true);
if (lookup.IsFound()) {
// We found an existing property. Unless it was an interceptor
// that claims the property is absent, skip this declaration.
@@ -2285,7 +2285,7 @@
}
LookupResult lookup(isolate);
- global->LocalLookup(name, &lookup, true);
+ global->LookupOwn(name, &lookup, true);
// Compute the property attributes. According to ECMA-262,
// the property must be non-configurable except in eval.
@@ -2302,7 +2302,7 @@
StrictMode strict_mode = DeclareGlobalsStrictMode::decode(flags);
if (!lookup.IsFound() || is_function) {
- // If the local property exists, check that we can reconfigure it
+ // If the own property exists, check that we can reconfigure it
// as required for function declarations.
if (lookup.IsFound() && lookup.IsDontDelete()) {
if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
@@ -2314,7 +2314,7 @@
}
// Define or redefine own property.
RETURN_FAILURE_ON_EXCEPTION(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
global, name, value, static_cast<PropertyAttributes>(attr)));
} else {
// Do a [[Put]] on the existing (own) property.
@@ -2400,7 +2400,7 @@
// Declare the property by setting it to the initial value if provided,
// or undefined, and use the correct mode (e.g. READ_ONLY attribute for
// constant declarations).
- ASSERT(!JSReceiver::HasLocalProperty(object, name));
+ ASSERT(!JSReceiver::HasOwnProperty(object, name));
Handle<Object> value(isolate->heap()->undefined_value(), isolate);
if (*initial_value != NULL) value = initial_value;
// Declaring a const context slot is a conflicting declaration if
@@ -2420,7 +2420,7 @@
if (object->IsJSGlobalObject()) {
// Define own property on the global object.
RETURN_FAILURE_ON_EXCEPTION(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
+ JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, mode));
} else {
RETURN_FAILURE_ON_EXCEPTION(isolate,
JSReceiver::SetProperty(object, name, value, mode, SLOPPY));
@@ -2449,15 +2449,15 @@
// not be deletable.
PropertyAttributes attributes = DONT_DELETE;
- // Lookup the property locally in the global object. If it isn't
+ // Lookup the property as own on the global object. If it isn't
// there, there is a property with this name in the prototype chain.
// We follow Safari and Firefox behavior and only set the property
- // locally if there is an explicit initialization value that we have
+ // if there is an explicit initialization value that we have
// to assign to the property.
// Note that objects can have hidden prototypes, so we need to traverse
- // the whole chain of hidden prototypes to do a 'local' lookup.
+ // the whole chain of hidden prototypes to do an 'own' lookup.
LookupResult lookup(isolate);
- isolate->context()->global_object()->LocalLookup(name, &lookup, true);
+ isolate->context()->global_object()->LookupOwn(name, &lookup, true);
if (lookup.IsInterceptor()) {
Handle<JSObject> holder(lookup.holder());
PropertyAttributes intercepted =
@@ -2508,20 +2508,19 @@
PropertyAttributes attributes =
static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
- // Lookup the property locally in the global object. If it isn't
+ // Lookup the property as own on the global object. If it isn't
// there, we add the property and take special precautions to always
- // add it as a local property even in case of callbacks in the
- // prototype chain (this rules out using SetProperty).
- // We use SetLocalPropertyIgnoreAttributes instead
+ // add it even in case of callbacks in the prototype chain (this rules
+ // out using SetProperty). We use SetOwnPropertyIgnoreAttributes instead
LookupResult lookup(isolate);
- global->LocalLookup(name, &lookup);
+ global->LookupOwn(name, &lookup);
if (!lookup.IsFound()) {
HandleScope handle_scope(isolate);
Handle<GlobalObject> global(isolate->context()->global_object());
RETURN_FAILURE_ON_EXCEPTION(
isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(global, name, value,
- attributes));
+ JSObject::SetOwnPropertyIgnoreAttributes(global, name, value,
+ attributes));
return *value;
}
@@ -2630,7 +2629,7 @@
// Set it if it hasn't been set before. NOTE: We cannot use
// GetProperty() to get the current value as it 'unholes' the value.
LookupResult lookup(isolate);
- object->LocalLookupRealNamedProperty(name, &lookup);
+ object->LookupOwnRealNamedProperty(name, &lookup);
ASSERT(lookup.IsFound()); // the property was declared
ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
@@ -2763,15 +2762,15 @@
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
Handle<Object> zero(Smi::FromInt(0), isolate);
Factory* factory = isolate->factory();
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
regexp, factory->source_string(), source, final).Check();
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
regexp, factory->global_string(), global, final).Check();
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
regexp, factory->ignore_case_string(), ignoreCase, final).Check();
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
regexp, factory->multiline_string(), multiline, final).Check();
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
regexp, factory->last_index_string(), zero, writable).Check();
return *regexp;
}
@@ -5043,11 +5042,11 @@
// Fast cases for getting named properties of the receiver JSObject
// itself.
//
- // The global proxy objects has to be excluded since LocalLookup on
+ // The global proxy objects has to be excluded since LookupOwn on
// the global proxy object can return a valid result even though the
// global proxy object never has properties. This is the case
// because the global proxy object forwards everything to its hidden
- // prototype including local lookups.
+ // prototype including own lookups.
//
// Additionally, we need to make sure that we do not cache results
// for objects that require access checks.
@@ -5073,7 +5072,7 @@
// Lookup cache miss. Perform lookup and update the cache if
// appropriate.
LookupResult result(isolate);
- receiver->LocalLookup(key, &result);
+ receiver->LookupOwn(key, &result);
if (result.IsField()) {
int offset = result.GetFieldIndex().field_index();
// Do not track double fields in the keyed lookup cache. Reading
@@ -5198,7 +5197,7 @@
}
LookupResult lookup(isolate);
- js_object->LocalLookupRealNamedProperty(name, &lookup);
+ js_object->LookupOwnRealNamedProperty(name, &lookup);
// Special case for callback properties.
if (lookup.IsPropertyCallbacks()) {
@@ -5243,7 +5242,7 @@
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
js_object, name, obj_value, attr));
return *result;
}
@@ -5397,7 +5396,7 @@
SLOPPY, false, DEFINE_PROPERTY);
} else {
if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
- return JSObject::SetLocalPropertyIgnoreAttributes(
+ return JSObject::SetOwnPropertyIgnoreAttributes(
js_object, name, value, attr, Object::OPTIMAL_REPRESENTATION,
ALLOW_AS_CONSTANT, JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
store_from_keyed);
@@ -5414,7 +5413,7 @@
return JSObject::SetElement(js_object, index, value, attr,
SLOPPY, false, DEFINE_PROPERTY);
} else {
- return JSObject::SetLocalPropertyIgnoreAttributes(
+ return JSObject::SetOwnPropertyIgnoreAttributes(
js_object, name, value, attr, Object::OPTIMAL_REPRESENTATION,
ALLOW_AS_CONSTANT, JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
store_from_keyed);
@@ -5647,7 +5646,7 @@
}
-// Set a local property, even if it is READ_ONLY. If the property does not
+// Set an own property, even if it is READ_ONLY. If the property does not
// exist, it will be added with attributes NONE.
RUNTIME_FUNCTION(Runtime_IgnoreAttributesAndSetProperty) {
HandleScope scope(isolate);
@@ -5667,7 +5666,7 @@
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
object, name, value, attributes));
return *result;
}
@@ -5689,10 +5688,10 @@
}
-static Object* HasLocalPropertyImplementation(Isolate* isolate,
- Handle<JSObject> object,
- Handle<Name> key) {
- if (JSReceiver::HasLocalProperty(object, key)) {
+static Object* HasOwnPropertyImplementation(Isolate* isolate,
+ Handle<JSObject> object,
+ Handle<Name> key) {
+ if (JSReceiver::HasOwnProperty(object, key)) {
return isolate->heap()->true_value();
}
// Handle hidden prototypes. If there's a hidden prototype above this thing
@@ -5701,16 +5700,16 @@
Handle<Object> proto(object->GetPrototype(), isolate);
if (proto->IsJSObject() &&
Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
- return HasLocalPropertyImplementation(isolate,
- Handle<JSObject>::cast(proto),
- key);
+ return HasOwnPropertyImplementation(isolate,
+ Handle<JSObject>::cast(proto),
+ key);
}
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->false_value();
}
-RUNTIME_FUNCTION(Runtime_HasLocalProperty) {
+RUNTIME_FUNCTION(Runtime_HasOwnProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0)
@@ -5738,9 +5737,9 @@
return isolate->heap()->false_value();
}
// Slow case.
- return HasLocalPropertyImplementation(isolate,
- Handle<JSObject>(js_obj),
- Handle<Name>(key));
+ return HasOwnPropertyImplementation(isolate,
+ Handle<JSObject>(js_obj),
+ Handle<Name>(key));
} else if (object->IsString() && key_is_array_index) {
// Well, there is one exception: Handle [] on strings.
Handle<String> string = Handle<String>::cast(object);
@@ -5784,7 +5783,7 @@
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
- PropertyAttributes att = JSReceiver::GetLocalPropertyAttribute(object, key);
+ PropertyAttributes att = JSReceiver::GetOwnPropertyAttribute(object, key);
if (att == ABSENT || (att & DONT_ENUM) != 0) {
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->false_value();
@@ -5836,10 +5835,10 @@
}
-// Find the length of the prototype chain that is to to handled as one. If a
+// Find the length of the prototype chain that is to be handled as one. If a
// prototype object is hidden it is to be viewed as part of the the object it
// is prototype for.
-static int LocalPrototypeChainLength(JSObject* obj) {
+static int OwnPrototypeChainLength(JSObject* obj) {
int count = 1;
Object* proto = obj->GetPrototype();
while (proto->IsJSObject() &&
@@ -5851,10 +5850,10 @@
}
-// Return the names of the local named properties.
+// Return the names of the own named properties.
// args[0]: object
// args[1]: PropertyAttributes as int
-RUNTIME_FUNCTION(Runtime_GetLocalPropertyNames) {
+RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
if (!args[0]->IsJSObject()) {
@@ -5879,10 +5878,10 @@
}
// Find the number of objects making up this.
- int length = LocalPrototypeChainLength(*obj);
+ int length = OwnPrototypeChainLength(*obj);
- // Find the number of local properties for each of the objects.
- ScopedVector<int> local_property_count(length);
+ // Find the number of own properties for each of the objects.
+ ScopedVector<int> own_property_count(length);
int total_property_count = 0;
Handle<JSObject> jsproto = obj;
for (int i = 0; i < length; i++) {
@@ -5895,8 +5894,8 @@
return *isolate->factory()->NewJSArray(0);
}
int n;
- n = jsproto->NumberOfLocalProperties(filter);
- local_property_count[i] = n;
+ n = jsproto->NumberOfOwnProperties(filter);
+ own_property_count[i] = n;
total_property_count += n;
if (i < length - 1) {
jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
@@ -5912,13 +5911,13 @@
int next_copy_index = 0;
int hidden_strings = 0;
for (int i = 0; i < length; i++) {
- jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
+ jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
if (i > 0) {
// Names from hidden prototypes may already have been added
// for inherited function template instances. Count the duplicates
// and stub them out; the final copy pass at the end ignores holes.
for (int j = next_copy_index;
- j < next_copy_index + local_property_count[i];
+ j < next_copy_index + own_property_count[i];
j++) {
Object* name_from_hidden_proto = names->get(j);
for (int k = 0; k < next_copy_index; k++) {
@@ -5933,7 +5932,7 @@
}
}
}
- next_copy_index += local_property_count[i];
+ next_copy_index += own_property_count[i];
// Hidden properties only show up if the filter does not skip strings.
if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) {
@@ -5966,9 +5965,9 @@
}
-// Return the names of the local indexed properties.
+// Return the names of the own indexed properties.
// args[0]: object
-RUNTIME_FUNCTION(Runtime_GetLocalElementNames) {
+RUNTIME_FUNCTION(Runtime_GetOwnElementNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
if (!args[0]->IsJSObject()) {
@@ -5976,9 +5975,9 @@
}
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
- int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
+ int n = obj->NumberOfOwnElements(static_cast<PropertyAttributes>(NONE));
Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
- obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
+ obj->GetOwnElementKeys(*names, static_cast<PropertyAttributes>(NONE));
return *isolate->factory()->NewJSArrayWithElements(names);
}
@@ -6035,7 +6034,7 @@
}
-RUNTIME_FUNCTION(Runtime_LocalKeys) {
+RUNTIME_FUNCTION(Runtime_OwnKeys) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
@@ -6060,7 +6059,7 @@
Handle<FixedArray> contents;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, contents,
- JSReceiver::GetKeys(object, JSReceiver::LOCAL_ONLY));
+ JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY));
// Some fast paths through GetKeysInFixedArrayFor reuse a cached
// property array and since the result is mutable we have to create
@@ -9476,7 +9475,7 @@
// Set the property if it's not read only or doesn't yet exist.
if ((attributes & READ_ONLY) == 0 ||
- (JSReceiver::GetLocalPropertyAttribute(object, name) == ABSENT)) {
+ (JSReceiver::GetOwnPropertyAttribute(object, name) == ABSENT)) {
RETURN_FAILURE_ON_EXCEPTION(
isolate,
JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
@@ -10716,9 +10715,8 @@
}
Handle<JSObject> current = Handle<JSObject>::cast(p);
Handle<FixedArray> current_keys =
- isolate->factory()->NewFixedArray(
- current->NumberOfLocalElements(NONE));
- current->GetLocalElementKeys(*current_keys, NONE);
+ isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE));
+ current->GetOwnElementKeys(*current_keys, NONE);
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, keys, FixedArray::UnionOfKeys(keys, current_keys));
}
@@ -10901,13 +10899,13 @@
}
// Find the number of objects making up this.
- int length = LocalPrototypeChainLength(*obj);
+ int length = OwnPrototypeChainLength(*obj);
- // Try local lookup on each of the objects.
+ // Try own lookup on each of the objects.
Handle<JSObject> jsproto = obj;
for (int i = 0; i < length; i++) {
LookupResult result(isolate);
- jsproto->LocalLookup(name, &result);
+ jsproto->LookupOwn(name, &result);
if (result.IsFound()) {
// LookupResult is not GC safe as it holds raw object pointers.
// GC can happen later in this code so put the required fields into
@@ -12842,8 +12840,8 @@
// Do not materialize the arguments object for eval or top-level code.
// Skip if "arguments" is already taken.
if (!function->shared()->is_function() ||
- JSReceiver::HasLocalProperty(target,
- isolate->factory()->arguments_string())) {
+ JSReceiver::HasOwnProperty(
+ target, isolate->factory()->arguments_string())) {
return target;
}
@@ -13115,14 +13113,6 @@
HandleScope scope(isolate);
ASSERT(args.length() == 3);
- // First perform a full GC in order to avoid references from dead objects.
- Heap* heap = isolate->heap();
- heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugReferencedBy");
- // The heap iterator reserves the right to do a GC to make the heap iterable.
- // Due to the GC above we know it won't need to do that, but it seems cleaner
- // to get the heap iterator constructed before we start having unprotected
- // Object* locals that are not protected by handles.
-
// Check parameters.
CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1);
@@ -13140,21 +13130,27 @@
// Get the number of referencing objects.
int count;
- HeapIterator heap_iterator(heap);
- count = DebugReferencedBy(&heap_iterator,
- *target, *instance_filter, max_references,
- NULL, 0, *arguments_function);
+ // First perform a full GC in order to avoid dead objects and to make the heap
+ // iterable.
+ Heap* heap = isolate->heap();
+ heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
+ {
+ HeapIterator heap_iterator(heap);
+ count = DebugReferencedBy(&heap_iterator,
+ *target, *instance_filter, max_references,
+ NULL, 0, *arguments_function);
+ }
// Allocate an array to hold the result.
Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
// Fill the referencing objects.
- // AllocateFixedArray above does not make the heap non-iterable.
- ASSERT(heap->IsHeapIterable());
- HeapIterator heap_iterator2(heap);
- count = DebugReferencedBy(&heap_iterator2,
- *target, *instance_filter, max_references,
- *instances, count, *arguments_function);
+ {
+ HeapIterator heap_iterator(heap);
+ count = DebugReferencedBy(&heap_iterator,
+ *target, *instance_filter, max_references,
+ *instances, count, *arguments_function);
+ }
// Return result as JS array.
Handle<JSFunction> constructor(
@@ -13205,9 +13201,6 @@
HandleScope scope(isolate);
ASSERT(args.length() == 2);
- // First perform a full GC in order to avoid dead objects.
- Heap* heap = isolate->heap();
- heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
// Check parameters.
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
@@ -13216,24 +13209,31 @@
// Get the number of referencing objects.
int count;
- HeapIterator heap_iterator(heap);
- count = DebugConstructedBy(&heap_iterator,
- *constructor,
- max_references,
- NULL,
- 0);
+ // First perform a full GC in order to avoid dead objects and to make the heap
+ // iterable.
+ Heap* heap = isolate->heap();
+ heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
+ {
+ HeapIterator heap_iterator(heap);
+ count = DebugConstructedBy(&heap_iterator,
+ *constructor,
+ max_references,
+ NULL,
+ 0);
+ }
// Allocate an array to hold the result.
Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
- ASSERT(heap->IsHeapIterable());
// Fill the referencing objects.
- HeapIterator heap_iterator2(heap);
- count = DebugConstructedBy(&heap_iterator2,
- *constructor,
- max_references,
- *instances,
- count);
+ {
+ HeapIterator heap_iterator2(heap);
+ count = DebugConstructedBy(&heap_iterator2,
+ *constructor,
+ max_references,
+ *instances,
+ count);
+ }
// Return result as JS array.
Handle<JSFunction> array_function(
@@ -13365,8 +13365,6 @@
int number;
Heap* heap = isolate->heap();
{
- heap->EnsureHeapIsIterable();
- DisallowHeapAllocation no_allocation;
HeapIterator heap_iterator(heap);
Script* scr = *script;
FixedArray* arr = *array;
@@ -13374,8 +13372,6 @@
}
if (number > kBufferSize) {
array = isolate->factory()->NewFixedArray(number);
- heap->EnsureHeapIsIterable();
- DisallowHeapAllocation no_allocation;
HeapIterator heap_iterator(heap);
Script* scr = *script;
FixedArray* arr = *array;
@@ -13778,7 +13774,7 @@
}
RETURN_FAILURE_ON_EXCEPTION(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
locales,
factory->NewStringFromAsciiChecked(result),
factory->NewNumber(i),
@@ -13883,13 +13879,13 @@
Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
RETURN_FAILURE_ON_EXCEPTION(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
result,
maximized,
factory->NewStringFromAsciiChecked(base_max_locale),
NONE));
RETURN_FAILURE_ON_EXCEPTION(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
result,
base,
factory->NewStringFromAsciiChecked(base_locale),
@@ -14011,7 +14007,7 @@
local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
RETURN_FAILURE_ON_EXCEPTION(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
local_object,
isolate->factory()->NewStringFromStaticAscii("dateFormat"),
isolate->factory()->NewStringFromStaticAscii("valid"),
@@ -14110,7 +14106,7 @@
local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
RETURN_FAILURE_ON_EXCEPTION(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
local_object,
isolate->factory()->NewStringFromStaticAscii("numberFormat"),
isolate->factory()->NewStringFromStaticAscii("valid"),
@@ -14218,7 +14214,7 @@
local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
RETURN_FAILURE_ON_EXCEPTION(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
local_object,
isolate->factory()->NewStringFromStaticAscii("collator"),
isolate->factory()->NewStringFromStaticAscii("valid"),
@@ -14324,7 +14320,7 @@
local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
RETURN_FAILURE_ON_EXCEPTION(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ JSObject::SetOwnPropertyIgnoreAttributes(
local_object,
isolate->factory()->NewStringFromStaticAscii("breakIterator"),
isolate->factory()->NewStringFromStaticAscii("valid"),
@@ -14458,8 +14454,6 @@
Handle<Script> script;
Factory* factory = script_name->GetIsolate()->factory();
Heap* heap = script_name->GetHeap();
- heap->EnsureHeapIsIterable();
- DisallowHeapAllocation no_allocation_during_heap_iteration;
HeapIterator iterator(heap);
HeapObject* obj = NULL;
while (script.is_null() && ((obj = iterator.next()) != NULL)) {
diff --git a/src/runtime.h b/src/runtime.h
index 1a93bf0..1332bae 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -26,14 +26,14 @@
F(GetProperty, 2, 1) \
F(KeyedGetProperty, 2, 1) \
F(DeleteProperty, 3, 1) \
- F(HasLocalProperty, 2, 1) \
+ F(HasOwnProperty, 2, 1) \
F(HasProperty, 2, 1) \
F(HasElement, 2, 1) \
F(IsPropertyEnumerable, 2, 1) \
F(GetPropertyNames, 1, 1) \
F(GetPropertyNamesFast, 1, 1) \
- F(GetLocalPropertyNames, 2, 1) \
- F(GetLocalElementNames, 1, 1) \
+ F(GetOwnPropertyNames, 2, 1) \
+ F(GetOwnElementNames, 1, 1) \
F(GetInterceptorInfo, 1, 1) \
F(GetNamedInterceptorPropertyNames, 1, 1) \
F(GetIndexedInterceptorElementNames, 1, 1) \
@@ -356,7 +356,7 @@
F(Abort, 1, 1) \
F(AbortJS, 1, 1) \
/* ES5 */ \
- F(LocalKeys, 1, 1) \
+ F(OwnKeys, 1, 1) \
\
/* Message objects */ \
F(MessageGetStartPosition, 1, 1) \
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index 1ed7e0b..14b8c4e 100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -539,7 +539,7 @@
int i = 0;
for (Interface::Iterator it = interface->iterator();
!it.done(); it.Advance(), ++i) {
- Variable* var = scope->LocalLookup(it.name());
+ Variable* var = scope->LookupLocal(it.name());
info->set_name(i, *it.name());
info->set_mode(i, var->mode());
ASSERT((var->mode() == MODULE) == (it.interface()->IsModule()));
diff --git a/src/scopes.cc b/src/scopes.cc
index 1818909..43b4f21 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -366,7 +366,7 @@
}
-Variable* Scope::LocalLookup(Handle<String> name) {
+Variable* Scope::LookupLocal(Handle<String> name) {
Variable* result = variables_.Lookup(name);
if (result != NULL || scope_info_.is_null()) {
return result;
@@ -425,7 +425,7 @@
for (Scope* scope = this;
scope != NULL;
scope = scope->outer_scope()) {
- Variable* var = scope->LocalLookup(name);
+ Variable* var = scope->LookupLocal(name);
if (var != NULL) return var;
}
return NULL;
@@ -950,7 +950,7 @@
}
// Try to find the variable in this scope.
- Variable* var = LocalLookup(name);
+ Variable* var = LookupLocal(name);
// We found a variable and we are done. (Even if there is an 'eval' in
// this scope which introduces the same variable again, the resulting
@@ -1211,7 +1211,7 @@
void Scope::AllocateParameterLocals() {
ASSERT(is_function_scope());
- Variable* arguments = LocalLookup(isolate_->factory()->arguments_string());
+ Variable* arguments = LookupLocal(isolate_->factory()->arguments_string());
ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
bool uses_sloppy_arguments = false;
diff --git a/src/scopes.h b/src/scopes.h
index 23a10f1..f6f5431 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -100,7 +100,7 @@
// Declarations
// Lookup a variable in this scope. Returns the variable or NULL if not found.
- Variable* LocalLookup(Handle<String> name);
+ Variable* LookupLocal(Handle<String> name);
// This lookup corresponds to a lookup in the "intermediate" scope sitting
// between this scope and the outer scope. (ECMA-262, 3rd., requires that
diff --git a/src/serialize.cc b/src/serialize.cc
index 2b43c0e..ab0f3ca 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -185,16 +185,6 @@
isolate);
}
- // Debug addresses
- Add(Debug_Address(Debug::k_after_break_target_address).address(isolate),
- DEBUG_ADDRESS,
- Debug::k_after_break_target_address << kDebugIdShift,
- "Debug::after_break_target_address()");
- Add(Debug_Address(Debug::k_restarter_frame_function_pointer).address(isolate),
- DEBUG_ADDRESS,
- Debug::k_restarter_frame_function_pointer << kDebugIdShift,
- "Debug::restarter_frame_function_pointer_address()");
-
// Stat counters
struct StatsRefTableEntry {
StatsCounter* (Counters::*counter)();
@@ -535,6 +525,18 @@
66,
"InvokeAccessorGetterCallback");
+ // Debug addresses
+ Add(ExternalReference::debug_after_break_target_address(isolate).address(),
+ UNCLASSIFIED,
+ 67,
+ "Debug::after_break_target_address()");
+
+ Add(ExternalReference::debug_restarter_frame_function_pointer_address(
+ isolate).address(),
+ UNCLASSIFIED,
+ 68,
+ "Debug::restarter_frame_function_pointer_address()");
+
// Add a small set of deopt entry addresses to encoder without generating the
// deopt table code, which isn't possible at deserialization time.
HandleScope scope(isolate);
@@ -563,7 +565,7 @@
uint32_t ExternalReferenceEncoder::Encode(Address key) const {
int index = IndexOf(key);
ASSERT(key == NULL || index >= 0);
- return index >=0 ?
+ return index >= 0 ?
ExternalReferenceTable::instance(isolate_)->code(index) : 0;
}
@@ -613,7 +615,6 @@
DeleteArray(encodings_);
}
-AtomicWord Serializer::serialization_state_ = SERIALIZER_STATE_UNINITIALIZED;
class CodeAddressMap: public CodeEventLogger {
public:
@@ -630,6 +631,9 @@
address_to_name_map_.Move(from, to);
}
+ virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) {
+ }
+
virtual void CodeDeleteEvent(Address from) {
address_to_name_map_.Remove(from);
}
@@ -723,48 +727,6 @@
};
-CodeAddressMap* Serializer::code_address_map_ = NULL;
-
-
-void Serializer::RequestEnable(Isolate* isolate) {
- isolate->InitializeLoggingAndCounters();
- code_address_map_ = new CodeAddressMap(isolate);
-}
-
-
-void Serializer::InitializeOncePerProcess() {
- // InitializeOncePerProcess is called by V8::InitializeOncePerProcess, a
- // method guaranteed to be called only once in a process lifetime.
- // serialization_state_ is read by many threads, hence the use of
- // Atomic primitives. Here, we don't need a barrier or mutex to
- // write it because V8 initialization is done by one thread, and gates
- // all reads of serialization_state_.
- ASSERT(NoBarrier_Load(&serialization_state_) ==
- SERIALIZER_STATE_UNINITIALIZED);
- SerializationState state = code_address_map_
- ? SERIALIZER_STATE_ENABLED
- : SERIALIZER_STATE_DISABLED;
- NoBarrier_Store(&serialization_state_, state);
-}
-
-
-void Serializer::TearDown() {
- // TearDown is called by V8::TearDown() for the default isolate. It's safe
- // to shut down the serializer by that point. Just to be safe, we restore
- // serialization_state_ to uninitialized.
- ASSERT(NoBarrier_Load(&serialization_state_) !=
- SERIALIZER_STATE_UNINITIALIZED);
- if (code_address_map_) {
- ASSERT(NoBarrier_Load(&serialization_state_) ==
- SERIALIZER_STATE_ENABLED);
- delete code_address_map_;
- code_address_map_ = NULL;
- }
-
- NoBarrier_Store(&serialization_state_, SERIALIZER_STATE_UNINITIALIZED);
-}
-
-
Deserializer::Deserializer(SnapshotByteSource* source)
: isolate_(NULL),
source_(source),
@@ -1262,7 +1224,8 @@
: isolate_(isolate),
sink_(sink),
external_reference_encoder_(new ExternalReferenceEncoder(isolate)),
- root_index_wave_front_(0) {
+ root_index_wave_front_(0),
+ code_address_map_(NULL) {
// The serializer is meant to be used only to generate initial heap images
// from a context in which there is only one isolate.
for (int i = 0; i <= LAST_SPACE; i++) {
@@ -1273,6 +1236,7 @@
Serializer::~Serializer() {
delete external_reference_encoder_;
+ if (code_address_map_ != NULL) delete code_address_map_;
}
@@ -1338,7 +1302,7 @@
// deserialized objects.
void SerializerDeserializer::Iterate(Isolate* isolate,
ObjectVisitor* visitor) {
- if (Serializer::enabled(isolate)) return;
+ if (isolate->serializer_enabled()) return;
for (int i = 0; ; i++) {
if (isolate->serialize_partial_snapshot_cache_length() <= i) {
// Extend the array ready to get a value from the visitor when
@@ -1578,12 +1542,14 @@
"ObjectSerialization");
sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
- ASSERT(code_address_map_);
- const char* code_name = code_address_map_->Lookup(object_->address());
- LOG(serializer_->isolate_,
- CodeNameEvent(object_->address(), sink_->Position(), code_name));
- LOG(serializer_->isolate_,
- SnapshotPositionEvent(object_->address(), sink_->Position()));
+ if (serializer_->code_address_map_) {
+ const char* code_name =
+ serializer_->code_address_map_->Lookup(object_->address());
+ LOG(serializer_->isolate_,
+ CodeNameEvent(object_->address(), sink_->Position(), code_name));
+ LOG(serializer_->isolate_,
+ SnapshotPositionEvent(object_->address(), sink_->Position()));
+ }
// Mark this object as already serialized.
int offset = serializer_->Allocate(space, size);
@@ -1863,6 +1829,12 @@
}
+void Serializer::InitializeCodeAddressMap() {
+ isolate_->InitializeLoggingAndCounters();
+ code_address_map_ = new CodeAddressMap(isolate_);
+}
+
+
bool SnapshotByteSource::AtEOF() {
if (0u + length_ - position_ > 2 * sizeof(uint32_t)) return false;
for (int x = position_; x < length_; x++) {
diff --git a/src/serialize.h b/src/serialize.h
index 958f20e..aaf97e3 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -17,7 +17,6 @@
BUILTIN,
RUNTIME_FUNCTION,
IC_UTILITY,
- DEBUG_ADDRESS,
STATS_COUNTER,
TOP_ADDRESS,
C_BUILTIN,
@@ -34,8 +33,6 @@
const int kReferenceIdBits = 16;
const int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
const int kReferenceTypeShift = kReferenceIdBits;
-const int kDebugRegisterBits = 4;
-const int kDebugIdShift = kDebugRegisterBits;
const int kDeoptTableSerializeEntryCount = 12;
@@ -60,7 +57,7 @@
private:
explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
- PopulateTable(isolate);
+ PopulateTable(isolate);
}
struct ExternalReferenceEntry {
@@ -447,16 +444,7 @@
}
Isolate* isolate() const { return isolate_; }
- static void RequestEnable(Isolate* isolate);
- static void InitializeOncePerProcess();
- static void TearDown();
- static bool enabled(Isolate* isolate) {
- SerializationState state = static_cast<SerializationState>(
- NoBarrier_Load(&serialization_state_));
- ASSERT(state != SERIALIZER_STATE_UNINITIALIZED);
- return state == SERIALIZER_STATE_ENABLED;
- }
SerializationAddressMapper* address_mapper() { return &address_mapper_; }
void PutRoot(int index,
HeapObject* object,
@@ -555,14 +543,6 @@
SnapshotByteSink* sink_;
ExternalReferenceEncoder* external_reference_encoder_;
- enum SerializationState {
- SERIALIZER_STATE_UNINITIALIZED = 0,
- SERIALIZER_STATE_DISABLED = 1,
- SERIALIZER_STATE_ENABLED = 2
- };
-
- static AtomicWord serialization_state_;
-
SerializationAddressMapper address_mapper_;
intptr_t root_index_wave_front_;
void Pad();
@@ -570,8 +550,12 @@
friend class ObjectSerializer;
friend class Deserializer;
+ // We may not need the code address map for logging for every instance
+ // of the serializer. Initialize it on demand.
+ void InitializeCodeAddressMap();
+
private:
- static CodeAddressMap* code_address_map_;
+ CodeAddressMap* code_address_map_;
DISALLOW_COPY_AND_ASSIGN(Serializer);
};
@@ -584,6 +568,7 @@
: Serializer(isolate, sink),
startup_serializer_(startup_snapshot_serializer) {
set_root_index_wave_front(Heap::kStrongRootListLength);
+ InitializeCodeAddressMap();
}
// Serialize the objects reachable from a single object pointer.
@@ -623,6 +608,7 @@
// which will repopulate the cache with objects needed by that partial
// snapshot.
isolate->set_serialize_partial_snapshot_cache_length(0);
+ InitializeCodeAddressMap();
}
// Serialize the current state of the heap. The order is:
// 1) Strong references.
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 6bf209b..3d11dc1 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -759,7 +759,7 @@
void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
Handle<Name> name,
LookupResult* lookup) {
- holder->LocalLookupRealNamedProperty(name, lookup);
+ holder->LookupOwnRealNamedProperty(name, lookup);
if (lookup->IsFound()) return;
if (holder->GetPrototype()->IsNull()) return;
holder->GetPrototype()->Lookup(name, lookup);
diff --git a/src/type-info.cc b/src/type-info.cc
index 83fcd0f..ca3baa1 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -97,9 +97,7 @@
bool TypeFeedbackOracle::CallIsMonomorphic(int slot) {
Handle<Object> value = GetInfo(slot);
- return FLAG_pretenuring_call_new
- ? value->IsJSFunction()
- : value->IsAllocationSite() || value->IsJSFunction();
+ return value->IsAllocationSite() || value->IsJSFunction();
}
@@ -134,7 +132,10 @@
Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(int slot) {
Handle<Object> info = GetInfo(slot);
- if (FLAG_pretenuring_call_new || info->IsJSFunction()) {
+ if (info->IsAllocationSite()) {
+ ASSERT(!FLAG_pretenuring_call_new);
+ return Handle<JSFunction>(isolate()->native_context()->array_function());
+ } else {
return Handle<JSFunction>::cast(info);
}
@@ -154,6 +155,15 @@
}
+Handle<AllocationSite> TypeFeedbackOracle::GetCallAllocationSite(int slot) {
+ Handle<Object> info = GetInfo(slot);
+ if (info->IsAllocationSite()) {
+ return Handle<AllocationSite>::cast(info);
+ }
+ return Handle<AllocationSite>::null();
+}
+
+
Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite(int slot) {
Handle<Object> info = GetInfo(slot);
if (FLAG_pretenuring_call_new || info->IsAllocationSite()) {
diff --git a/src/type-info.h b/src/type-info.h
index 24a9edb..6b99826 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -65,6 +65,7 @@
Context* native_context);
Handle<JSFunction> GetCallTarget(int slot);
+ Handle<AllocationSite> GetCallAllocationSite(int slot);
Handle<JSFunction> GetCallNewTarget(int slot);
Handle<AllocationSite> GetCallNewAllocationSite(int slot);
diff --git a/src/typing.cc b/src/typing.cc
index 434aff34..f32f0eb 100644
--- a/src/typing.cc
+++ b/src/typing.cc
@@ -511,6 +511,9 @@
expr->IsUsingCallFeedbackSlot(isolate()) &&
oracle()->CallIsMonomorphic(expr->CallFeedbackSlot())) {
expr->set_target(oracle()->GetCallTarget(expr->CallFeedbackSlot()));
+ Handle<AllocationSite> site =
+ oracle()->GetCallAllocationSite(expr->CallFeedbackSlot());
+ expr->set_allocation_site(site);
}
ZoneList<Expression*>* args = expr->arguments();
diff --git a/src/uri.js b/src/uri.js
index fb9742f..4b7d1f7 100644
--- a/src/uri.js
+++ b/src/uri.js
@@ -13,431 +13,380 @@
// This file contains support for URI manipulations written in
// JavaScript.
-// Lazily initialized.
-var hexCharArray = 0;
-var hexCharCodeArray = 0;
+(function() {
-function URIAddEncodedOctetToBuffer(octet, result, index) {
- result[index++] = 37; // Char code of '%'.
- result[index++] = hexCharCodeArray[octet >> 4];
- result[index++] = hexCharCodeArray[octet & 0x0F];
- return index;
-}
+ // -------------------------------------------------------------------
+ // Define internal helper functions.
+ function HexValueOf(code) {
+ // 0-9
+ if (code >= 48 && code <= 57) return code - 48;
+ // A-F
+ if (code >= 65 && code <= 70) return code - 55;
+ // a-f
+ if (code >= 97 && code <= 102) return code - 87;
-function URIEncodeOctets(octets, result, index) {
- if (hexCharCodeArray === 0) {
- hexCharCodeArray = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 65, 66, 67, 68, 69, 70];
+ return -1;
}
- index = URIAddEncodedOctetToBuffer(octets[0], result, index);
- if (octets[1]) index = URIAddEncodedOctetToBuffer(octets[1], result, index);
- if (octets[2]) index = URIAddEncodedOctetToBuffer(octets[2], result, index);
- if (octets[3]) index = URIAddEncodedOctetToBuffer(octets[3], result, index);
- return index;
-}
+ // Does the char code correspond to an alpha-numeric char.
+ function isAlphaNumeric(cc) {
+ // a - z
+ if (97 <= cc && cc <= 122) return true;
+ // A - Z
+ if (65 <= cc && cc <= 90) return true;
+ // 0 - 9
+ if (48 <= cc && cc <= 57) return true;
-function URIEncodeSingle(cc, result, index) {
- var x = (cc >> 12) & 0xF;
- var y = (cc >> 6) & 63;
- var z = cc & 63;
- var octets = new $Array(3);
- if (cc <= 0x007F) {
- octets[0] = cc;
- } else if (cc <= 0x07FF) {
- octets[0] = y + 192;
- octets[1] = z + 128;
- } else {
- octets[0] = x + 224;
- octets[1] = y + 128;
- octets[2] = z + 128;
+ return false;
}
- return URIEncodeOctets(octets, result, index);
-}
+ //Lazily initialized.
+ var hexCharCodeArray = 0;
-function URIEncodePair(cc1 , cc2, result, index) {
- var u = ((cc1 >> 6) & 0xF) + 1;
- var w = (cc1 >> 2) & 0xF;
- var x = cc1 & 3;
- var y = (cc2 >> 6) & 0xF;
- var z = cc2 & 63;
- var octets = new $Array(4);
- octets[0] = (u >> 2) + 240;
- octets[1] = (((u & 3) << 4) | w) + 128;
- octets[2] = ((x << 4) | y) + 128;
- octets[3] = z + 128;
- return URIEncodeOctets(octets, result, index);
-}
-
-
-function URIHexCharsToCharCode(highChar, lowChar) {
- var highCode = HexValueOf(highChar);
- var lowCode = HexValueOf(lowChar);
- if (highCode == -1 || lowCode == -1) {
- throw new $URIError("URI malformed");
+ function URIAddEncodedOctetToBuffer(octet, result, index) {
+ result[index++] = 37; // Char code of '%'.
+ result[index++] = hexCharCodeArray[octet >> 4];
+ result[index++] = hexCharCodeArray[octet & 0x0F];
+ return index;
}
- return (highCode << 4) | lowCode;
-}
+ function URIEncodeOctets(octets, result, index) {
+ if (hexCharCodeArray === 0) {
+ hexCharCodeArray = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 65, 66, 67, 68, 69, 70];
+ }
+ index = URIAddEncodedOctetToBuffer(octets[0], result, index);
+ if (octets[1]) index = URIAddEncodedOctetToBuffer(octets[1], result, index);
+ if (octets[2]) index = URIAddEncodedOctetToBuffer(octets[2], result, index);
+ if (octets[3]) index = URIAddEncodedOctetToBuffer(octets[3], result, index);
+ return index;
+ }
-function URIDecodeOctets(octets, result, index) {
- if (!IS_STRING(result)) throw new $URIError("Internal error");
- var value;
- var o0 = octets[0];
- if (o0 < 0x80) {
- value = o0;
- } else if (o0 < 0xc2) {
- throw new $URIError("URI malformed");
- } else {
- var o1 = octets[1];
- if (o0 < 0xe0) {
- var a = o0 & 0x1f;
- if ((o1 < 0x80) || (o1 > 0xbf)) {
- throw new $URIError("URI malformed");
- }
- var b = o1 & 0x3f;
- value = (a << 6) + b;
- if (value < 0x80 || value > 0x7ff) {
- throw new $URIError("URI malformed");
- }
+ function URIEncodeSingle(cc, result, index) {
+ var x = (cc >> 12) & 0xF;
+ var y = (cc >> 6) & 63;
+ var z = cc & 63;
+ var octets = new $Array(3);
+ if (cc <= 0x007F) {
+ octets[0] = cc;
+ } else if (cc <= 0x07FF) {
+ octets[0] = y + 192;
+ octets[1] = z + 128;
} else {
- var o2 = octets[2];
- if (o0 < 0xf0) {
- var a = o0 & 0x0f;
+ octets[0] = x + 224;
+ octets[1] = y + 128;
+ octets[2] = z + 128;
+ }
+ return URIEncodeOctets(octets, result, index);
+ }
+
+ function URIEncodePair(cc1 , cc2, result, index) {
+ var u = ((cc1 >> 6) & 0xF) + 1;
+ var w = (cc1 >> 2) & 0xF;
+ var x = cc1 & 3;
+ var y = (cc2 >> 6) & 0xF;
+ var z = cc2 & 63;
+ var octets = new $Array(4);
+ octets[0] = (u >> 2) + 240;
+ octets[1] = (((u & 3) << 4) | w) + 128;
+ octets[2] = ((x << 4) | y) + 128;
+ octets[3] = z + 128;
+ return URIEncodeOctets(octets, result, index);
+ }
+
+ function URIHexCharsToCharCode(highChar, lowChar) {
+ var highCode = HexValueOf(highChar);
+ var lowCode = HexValueOf(lowChar);
+ if (highCode == -1 || lowCode == -1) {
+ throw new $URIError("URI malformed");
+ }
+ return (highCode << 4) | lowCode;
+ }
+
+ // Callers must ensure that |result| is a sufficiently long sequential
+ // two-byte string!
+ function URIDecodeOctets(octets, result, index) {
+ var value;
+ var o0 = octets[0];
+ if (o0 < 0x80) {
+ value = o0;
+ } else if (o0 < 0xc2) {
+ throw new $URIError("URI malformed");
+ } else {
+ var o1 = octets[1];
+ if (o0 < 0xe0) {
+ var a = o0 & 0x1f;
if ((o1 < 0x80) || (o1 > 0xbf)) {
throw new $URIError("URI malformed");
}
var b = o1 & 0x3f;
- if ((o2 < 0x80) || (o2 > 0xbf)) {
- throw new $URIError("URI malformed");
- }
- var c = o2 & 0x3f;
- value = (a << 12) + (b << 6) + c;
- if ((value < 0x800) || (value > 0xffff)) {
+ value = (a << 6) + b;
+ if (value < 0x80 || value > 0x7ff) {
throw new $URIError("URI malformed");
}
} else {
- var o3 = octets[3];
- if (o0 < 0xf8) {
- var a = (o0 & 0x07);
+ var o2 = octets[2];
+ if (o0 < 0xf0) {
+ var a = o0 & 0x0f;
if ((o1 < 0x80) || (o1 > 0xbf)) {
throw new $URIError("URI malformed");
}
- var b = (o1 & 0x3f);
+ var b = o1 & 0x3f;
if ((o2 < 0x80) || (o2 > 0xbf)) {
throw new $URIError("URI malformed");
}
- var c = (o2 & 0x3f);
- if ((o3 < 0x80) || (o3 > 0xbf)) {
- throw new $URIError("URI malformed");
- }
- var d = (o3 & 0x3f);
- value = (a << 18) + (b << 12) + (c << 6) + d;
- if ((value < 0x10000) || (value > 0x10ffff)) {
+ var c = o2 & 0x3f;
+ value = (a << 12) + (b << 6) + c;
+ if ((value < 0x800) || (value > 0xffff)) {
throw new $URIError("URI malformed");
}
} else {
- throw new $URIError("URI malformed");
+ var o3 = octets[3];
+ if (o0 < 0xf8) {
+ var a = (o0 & 0x07);
+ if ((o1 < 0x80) || (o1 > 0xbf)) {
+ throw new $URIError("URI malformed");
+ }
+ var b = (o1 & 0x3f);
+ if ((o2 < 0x80) || (o2 > 0xbf)) {
+ throw new $URIError("URI malformed");
+ }
+ var c = (o2 & 0x3f);
+ if ((o3 < 0x80) || (o3 > 0xbf)) {
+ throw new $URIError("URI malformed");
+ }
+ var d = (o3 & 0x3f);
+ value = (a << 18) + (b << 12) + (c << 6) + d;
+ if ((value < 0x10000) || (value > 0x10ffff)) {
+ throw new $URIError("URI malformed");
+ }
+ } else {
+ throw new $URIError("URI malformed");
+ }
}
}
}
- }
- if (0xD800 <= value && value <= 0xDFFF) {
- throw new $URIError("URI malformed");
- }
- if (value < 0x10000) {
- if (index < 0 || index >= result.length) {
- throw new $URIError("Internal error");
+ if (0xD800 <= value && value <= 0xDFFF) {
+ throw new $URIError("URI malformed");
}
- %_TwoByteSeqStringSetChar(result, index++, value);
- return index;
- } else {
- if (index < 0 || index >= result.length - 1) {
- throw new $URIError("Internal error");
+ if (value < 0x10000) {
+ %_TwoByteSeqStringSetChar(result, index++, value);
+ } else {
+ %_TwoByteSeqStringSetChar(result, index++, (value >> 10) + 0xd7c0);
+ %_TwoByteSeqStringSetChar(result, index++, (value & 0x3ff) + 0xdc00);
}
- %_TwoByteSeqStringSetChar(result, index++, (value >> 10) + 0xd7c0);
- %_TwoByteSeqStringSetChar(result, index++, (value & 0x3ff) + 0xdc00);
return index;
}
-}
-
-// ECMA-262, section 15.1.3
-function Encode(uri, unescape) {
- var uriLength = uri.length;
- var array = new InternalArray(uriLength);
- var index = 0;
- for (var k = 0; k < uriLength; k++) {
- var cc1 = uri.charCodeAt(k);
- if (unescape(cc1)) {
- array[index++] = cc1;
- } else {
- if (cc1 >= 0xDC00 && cc1 <= 0xDFFF) throw new $URIError("URI malformed");
- if (cc1 < 0xD800 || cc1 > 0xDBFF) {
- index = URIEncodeSingle(cc1, array, index);
+ // ECMA-262, section 15.1.3
+ function Encode(uri, unescape) {
+ var uriLength = uri.length;
+ var array = new InternalArray(uriLength);
+ var index = 0;
+ for (var k = 0; k < uriLength; k++) {
+ var cc1 = uri.charCodeAt(k);
+ if (unescape(cc1)) {
+ array[index++] = cc1;
} else {
- k++;
- if (k == uriLength) throw new $URIError("URI malformed");
- var cc2 = uri.charCodeAt(k);
- if (cc2 < 0xDC00 || cc2 > 0xDFFF) throw new $URIError("URI malformed");
- index = URIEncodePair(cc1, cc2, array, index);
- }
- }
- }
-
- var result = %NewString(array.length, NEW_ONE_BYTE_STRING);
- for (var i = 0; i < array.length; i++) {
- %_OneByteSeqStringSetChar(result, i, array[i]);
- }
- return result;
-}
-
-
-// ECMA-262, section 15.1.3
-function Decode(uri, reserved) {
- var uriLength = uri.length;
- var one_byte = %NewString(uriLength, NEW_ONE_BYTE_STRING);
- var index = 0;
- var k = 0;
-
- // Optimistically assume ascii string.
- for ( ; k < uriLength; k++) {
- var code = uri.charCodeAt(k);
- if (code == 37) { // '%'
- if (k + 2 >= uriLength) throw new $URIError("URI malformed");
- var cc = URIHexCharsToCharCode(uri.charCodeAt(k+1), uri.charCodeAt(k+2));
- if (cc >> 7) break; // Assumption wrong, two byte string.
- if (reserved(cc)) {
- %_OneByteSeqStringSetChar(one_byte, index++, 37); // '%'.
- %_OneByteSeqStringSetChar(one_byte, index++, uri.charCodeAt(k+1));
- %_OneByteSeqStringSetChar(one_byte, index++, uri.charCodeAt(k+2));
- } else {
- %_OneByteSeqStringSetChar(one_byte, index++, cc);
- }
- k += 2;
- } else {
- if (code > 0x7f) break; // Assumption wrong, two byte string.
- %_OneByteSeqStringSetChar(one_byte, index++, code);
- }
- }
-
- one_byte = %TruncateString(one_byte, index);
- if (k == uriLength) return one_byte;
-
- // Write into two byte string.
- var two_byte = %NewString(uriLength - k, NEW_TWO_BYTE_STRING);
- index = 0;
-
- for ( ; k < uriLength; k++) {
- var code = uri.charCodeAt(k);
- if (code == 37) { // '%'
- if (k + 2 >= uriLength) throw new $URIError("URI malformed");
- var cc = URIHexCharsToCharCode(uri.charCodeAt(++k), uri.charCodeAt(++k));
- if (cc >> 7) {
- var n = 0;
- while (((cc << ++n) & 0x80) != 0) { }
- if (n == 1 || n > 4) throw new $URIError("URI malformed");
- var octets = new $Array(n);
- octets[0] = cc;
- if (k + 3 * (n - 1) >= uriLength) throw new $URIError("URI malformed");
- for (var i = 1; i < n; i++) {
- if (uri.charAt(++k) != '%') throw new $URIError("URI malformed");
- octets[i] = URIHexCharsToCharCode(uri.charCodeAt(++k),
- uri.charCodeAt(++k));
+ if (cc1 >= 0xDC00 && cc1 <= 0xDFFF) throw new $URIError("URI malformed");
+ if (cc1 < 0xD800 || cc1 > 0xDBFF) {
+ index = URIEncodeSingle(cc1, array, index);
+ } else {
+ k++;
+ if (k == uriLength) throw new $URIError("URI malformed");
+ var cc2 = uri.charCodeAt(k);
+ if (cc2 < 0xDC00 || cc2 > 0xDFFF) throw new $URIError("URI malformed");
+ index = URIEncodePair(cc1, cc2, array, index);
}
- index = URIDecodeOctets(octets, two_byte, index);
- } else if (reserved(cc)) {
- %_TwoByteSeqStringSetChar(two_byte, index++, 37); // '%'.
- %_TwoByteSeqStringSetChar(two_byte, index++, uri.charCodeAt(k - 1));
- %_TwoByteSeqStringSetChar(two_byte, index++, uri.charCodeAt(k));
- } else {
- %_TwoByteSeqStringSetChar(two_byte, index++, cc);
}
- } else {
- %_TwoByteSeqStringSetChar(two_byte, index++, code);
}
+
+ var result = %NewString(array.length, NEW_ONE_BYTE_STRING);
+ for (var i = 0; i < array.length; i++) {
+ %_OneByteSeqStringSetChar(result, i, array[i]);
+ }
+ return result;
}
- two_byte = %TruncateString(two_byte, index);
- return one_byte + two_byte;
-}
+ // ECMA-262, section 15.1.3
+ function Decode(uri, reserved) {
+ var uriLength = uri.length;
+ var one_byte = %NewString(uriLength, NEW_ONE_BYTE_STRING);
+ var index = 0;
+ var k = 0;
+ // Optimistically assume ascii string.
+ for ( ; k < uriLength; k++) {
+ var code = uri.charCodeAt(k);
+ if (code == 37) { // '%'
+ if (k + 2 >= uriLength) throw new $URIError("URI malformed");
+ var cc = URIHexCharsToCharCode(uri.charCodeAt(k+1), uri.charCodeAt(k+2));
+ if (cc >> 7) break; // Assumption wrong, two byte string.
+ if (reserved(cc)) {
+ %_OneByteSeqStringSetChar(one_byte, index++, 37); // '%'.
+ %_OneByteSeqStringSetChar(one_byte, index++, uri.charCodeAt(k+1));
+ %_OneByteSeqStringSetChar(one_byte, index++, uri.charCodeAt(k+2));
+ } else {
+ %_OneByteSeqStringSetChar(one_byte, index++, cc);
+ }
+ k += 2;
+ } else {
+ if (code > 0x7f) break; // Assumption wrong, two byte string.
+ %_OneByteSeqStringSetChar(one_byte, index++, code);
+ }
+ }
-// ECMA-262 - 15.1.3.1.
-function URIDecode(uri) {
- var reservedPredicate = function(cc) {
- // #$
- if (35 <= cc && cc <= 36) return true;
- // &
- if (cc == 38) return true;
- // +,
- if (43 <= cc && cc <= 44) return true;
- // /
- if (cc == 47) return true;
- // :;
- if (58 <= cc && cc <= 59) return true;
- // =
- if (cc == 61) return true;
- // ?@
- if (63 <= cc && cc <= 64) return true;
+ one_byte = %TruncateString(one_byte, index);
+ if (k == uriLength) return one_byte;
- return false;
- };
- var string = ToString(uri);
- return Decode(string, reservedPredicate);
-}
+ // Write into two byte string.
+ var two_byte = %NewString(uriLength - k, NEW_TWO_BYTE_STRING);
+ index = 0;
+ for ( ; k < uriLength; k++) {
+ var code = uri.charCodeAt(k);
+ if (code == 37) { // '%'
+ if (k + 2 >= uriLength) throw new $URIError("URI malformed");
+ var cc = URIHexCharsToCharCode(uri.charCodeAt(++k), uri.charCodeAt(++k));
+ if (cc >> 7) {
+ var n = 0;
+ while (((cc << ++n) & 0x80) != 0) { }
+ if (n == 1 || n > 4) throw new $URIError("URI malformed");
+ var octets = new $Array(n);
+ octets[0] = cc;
+ if (k + 3 * (n - 1) >= uriLength) throw new $URIError("URI malformed");
+ for (var i = 1; i < n; i++) {
+ if (uri.charAt(++k) != '%') throw new $URIError("URI malformed");
+ octets[i] = URIHexCharsToCharCode(uri.charCodeAt(++k),
+ uri.charCodeAt(++k));
+ }
+ index = URIDecodeOctets(octets, two_byte, index);
+ } else if (reserved(cc)) {
+ %_TwoByteSeqStringSetChar(two_byte, index++, 37); // '%'.
+ %_TwoByteSeqStringSetChar(two_byte, index++, uri.charCodeAt(k - 1));
+ %_TwoByteSeqStringSetChar(two_byte, index++, uri.charCodeAt(k));
+ } else {
+ %_TwoByteSeqStringSetChar(two_byte, index++, cc);
+ }
+ } else {
+ %_TwoByteSeqStringSetChar(two_byte, index++, code);
+ }
+ }
-// ECMA-262 - 15.1.3.2.
-function URIDecodeComponent(component) {
- var reservedPredicate = function(cc) { return false; };
- var string = ToString(component);
- return Decode(string, reservedPredicate);
-}
-
-
-// Does the char code correspond to an alpha-numeric char.
-function isAlphaNumeric(cc) {
- // a - z
- if (97 <= cc && cc <= 122) return true;
- // A - Z
- if (65 <= cc && cc <= 90) return true;
- // 0 - 9
- if (48 <= cc && cc <= 57) return true;
-
- return false;
-}
-
-
-// ECMA-262 - 15.1.3.3.
-function URIEncode(uri) {
- var unescapePredicate = function(cc) {
- if (isAlphaNumeric(cc)) return true;
- // !
- if (cc == 33) return true;
- // #$
- if (35 <= cc && cc <= 36) return true;
- // &'()*+,-./
- if (38 <= cc && cc <= 47) return true;
- // :;
- if (58 <= cc && cc <= 59) return true;
- // =
- if (cc == 61) return true;
- // ?@
- if (63 <= cc && cc <= 64) return true;
- // _
- if (cc == 95) return true;
- // ~
- if (cc == 126) return true;
-
- return false;
- };
-
- var string = ToString(uri);
- return Encode(string, unescapePredicate);
-}
-
-
-// ECMA-262 - 15.1.3.4
-function URIEncodeComponent(component) {
- var unescapePredicate = function(cc) {
- if (isAlphaNumeric(cc)) return true;
- // !
- if (cc == 33) return true;
- // '()*
- if (39 <= cc && cc <= 42) return true;
- // -.
- if (45 <= cc && cc <= 46) return true;
- // _
- if (cc == 95) return true;
- // ~
- if (cc == 126) return true;
-
- return false;
- };
-
- var string = ToString(component);
- return Encode(string, unescapePredicate);
-}
-
-
-function HexValueOf(code) {
- // 0-9
- if (code >= 48 && code <= 57) return code - 48;
- // A-F
- if (code >= 65 && code <= 70) return code - 55;
- // a-f
- if (code >= 97 && code <= 102) return code - 87;
-
- return -1;
-}
-
-
-// Convert a character code to 4-digit hex string representation
-// 64 -> 0040, 62234 -> F31A.
-function CharCodeToHex4Str(cc) {
- var r = "";
- if (hexCharArray === 0) {
- hexCharArray = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
- "A", "B", "C", "D", "E", "F"];
+ two_byte = %TruncateString(two_byte, index);
+ return one_byte + two_byte;
}
- for (var i = 0; i < 4; ++i) {
- var c = hexCharArray[cc & 0x0F];
- r = c + r;
- cc = cc >>> 4;
+
+ // -------------------------------------------------------------------
+ // Define exported functions.
+
+ // ECMA-262 - B.2.1.
+ function URIEscapeJS(str) {
+ var s = ToString(str);
+ return %URIEscape(s);
}
- return r;
-}
+ // ECMA-262 - B.2.2.
+ function URIUnescapeJS(str) {
+ var s = ToString(str);
+ return %URIUnescape(s);
+ }
-// Returns true if all digits in string s are valid hex numbers
-function IsValidHex(s) {
- for (var i = 0; i < s.length; ++i) {
- var cc = s.charCodeAt(i);
- if ((48 <= cc && cc <= 57) ||
- (65 <= cc && cc <= 70) ||
- (97 <= cc && cc <= 102)) {
- // '0'..'9', 'A'..'F' and 'a' .. 'f'.
- } else {
+ // ECMA-262 - 15.1.3.1.
+ function URIDecode(uri) {
+ var reservedPredicate = function(cc) {
+ // #$
+ if (35 <= cc && cc <= 36) return true;
+ // &
+ if (cc == 38) return true;
+ // +,
+ if (43 <= cc && cc <= 44) return true;
+ // /
+ if (cc == 47) return true;
+ // :;
+ if (58 <= cc && cc <= 59) return true;
+ // =
+ if (cc == 61) return true;
+ // ?@
+ if (63 <= cc && cc <= 64) return true;
+
return false;
- }
+ };
+ var string = ToString(uri);
+ return Decode(string, reservedPredicate);
}
- return true;
-}
+ // ECMA-262 - 15.1.3.2.
+ function URIDecodeComponent(component) {
+ var reservedPredicate = function(cc) { return false; };
+ var string = ToString(component);
+ return Decode(string, reservedPredicate);
+ }
-// ECMA-262 - B.2.1.
-function URIEscapeJS(str) {
- var s = ToString(str);
- return %URIEscape(s);
-}
+ // ECMA-262 - 15.1.3.3.
+ function URIEncode(uri) {
+ var unescapePredicate = function(cc) {
+ if (isAlphaNumeric(cc)) return true;
+ // !
+ if (cc == 33) return true;
+ // #$
+ if (35 <= cc && cc <= 36) return true;
+ // &'()*+,-./
+ if (38 <= cc && cc <= 47) return true;
+ // :;
+ if (58 <= cc && cc <= 59) return true;
+ // =
+ if (cc == 61) return true;
+ // ?@
+ if (63 <= cc && cc <= 64) return true;
+ // _
+ if (cc == 95) return true;
+ // ~
+ if (cc == 126) return true;
+ return false;
+ };
+ var string = ToString(uri);
+ return Encode(string, unescapePredicate);
+ }
-// ECMA-262 - B.2.2.
-function URIUnescapeJS(str) {
- var s = ToString(str);
- return %URIUnescape(s);
-}
+ // ECMA-262 - 15.1.3.4
+ function URIEncodeComponent(component) {
+ var unescapePredicate = function(cc) {
+ if (isAlphaNumeric(cc)) return true;
+ // !
+ if (cc == 33) return true;
+ // '()*
+ if (39 <= cc && cc <= 42) return true;
+ // -.
+ if (45 <= cc && cc <= 46) return true;
+ // _
+ if (cc == 95) return true;
+ // ~
+ if (cc == 126) return true;
+ return false;
+ };
+ var string = ToString(component);
+ return Encode(string, unescapePredicate);
+ }
-// -------------------------------------------------------------------
+ // -------------------------------------------------------------------
+ // Install exported functions.
-function SetUpUri() {
%CheckIsBootstrapping();
// Set up non-enumerable URI functions on the global object and set
// their names.
InstallFunctions(global, DONT_ENUM, $Array(
- "escape", URIEscapeJS,
- "unescape", URIUnescapeJS,
- "decodeURI", URIDecode,
- "decodeURIComponent", URIDecodeComponent,
- "encodeURI", URIEncode,
- "encodeURIComponent", URIEncodeComponent
+ "escape", URIEscapeJS,
+ "unescape", URIUnescapeJS,
+ "decodeURI", URIDecode,
+ "decodeURIComponent", URIDecodeComponent,
+ "encodeURI", URIEncode,
+ "encodeURIComponent", URIEncodeComponent
));
-}
-SetUpUri();
+})();
diff --git a/src/v8.cc b/src/v8.cc
index 08afb54..0048340 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -61,7 +61,6 @@
Isolate::GlobalTearDown();
Sampler::TearDown();
- Serializer::TearDown();
#ifdef V8_USE_DEFAULT_PLATFORM
DefaultPlatform* platform = static_cast<DefaultPlatform*>(platform_);
@@ -79,7 +78,6 @@
void V8::InitializeOncePerProcessImpl() {
FlagList::EnforceFlagImplications();
- Serializer::InitializeOncePerProcess();
if (FLAG_predictable && FLAG_random_seed == 0) {
// Avoid random seeds in predictable mode.
diff --git a/src/v8natives.js b/src/v8natives.js
index 1a50a84..4bbbac5 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -244,7 +244,7 @@
var handler = %GetHandler(this);
return CallTrap1(handler, "hasOwn", DerivedHasOwnTrap, ToName(V));
}
- return %HasLocalProperty(TO_OBJECT_INLINE(this), ToName(V));
+ return %HasOwnProperty(TO_OBJECT_INLINE(this), ToName(V));
}
@@ -332,7 +332,7 @@
var names = CallTrap0(handler, "keys", DerivedKeysTrap);
return ToNameArray(names, "keys", false);
}
- return %LocalKeys(obj);
+ return %OwnKeys(obj);
}
@@ -1025,7 +1025,7 @@
var s = ToName(obj[index]);
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(s) && !includeSymbols) continue;
- if (%HasLocalProperty(names, s)) {
+ if (%HasOwnProperty(names, s)) {
throw MakeTypeError("proxy_repeated_prop_name", [obj, trap, s]);
}
array[index] = s;
@@ -1045,13 +1045,13 @@
// Find all the indexed properties.
- // Only get the local element names if we want to include string keys.
+ // Only get own element names if we want to include string keys.
if (!symbolsOnly) {
- var localElementNames = %GetLocalElementNames(obj);
- for (var i = 0; i < localElementNames.length; ++i) {
- localElementNames[i] = %_NumberToString(localElementNames[i]);
+ var ownElementNames = %GetOwnElementNames(obj);
+ for (var i = 0; i < ownElementNames.length; ++i) {
+ ownElementNames[i] = %_NumberToString(ownElementNames[i]);
}
- nameArrays.push(localElementNames);
+ nameArrays.push(ownElementNames);
// Get names for indexed interceptor properties.
var interceptorInfo = %GetInterceptorInfo(obj);
@@ -1065,8 +1065,8 @@
// Find all the named properties.
- // Get the local property names.
- nameArrays.push(%GetLocalPropertyNames(obj, filter));
+ // Get own property names.
+ nameArrays.push(%GetOwnPropertyNames(obj, filter));
// Get names for named interceptor properties if any.
if ((interceptorInfo & 2) != 0) {
@@ -1156,7 +1156,7 @@
{value: 0, writable: 0, get: 0, set: 0, enumerable: 0, configurable: 0};
for (var i = 0; i < names.length; i++) {
var N = names[i];
- if (!(%HasLocalProperty(standardNames, N))) {
+ if (!(%HasOwnProperty(standardNames, N))) {
var attr = GetOwnPropertyJS(attributes, N);
DefineOwnProperty(descObj, N, attr, true);
}
@@ -1176,7 +1176,7 @@
function GetOwnEnumerablePropertyNames(properties) {
var names = new InternalArray();
for (var key in properties) {
- if (%HasLocalProperty(properties, key)) {
+ if (%HasOwnProperty(properties, key)) {
names.push(key);
}
}
diff --git a/src/version.cc b/src/version.cc
index f917194..cd81ed7 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 27
-#define BUILD_NUMBER 10
+#define BUILD_NUMBER 11
#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/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 0e53eb3..a63288f 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -2228,16 +2228,17 @@
}
-void CallFunctionStub::Generate(MacroAssembler* masm) {
+static void CallFunctionNoFeedback(MacroAssembler* masm,
+ int argc, bool needs_checks,
+ bool call_as_method) {
// rdi : the function to call
// wrap_and_call can only be true if we are compiling a monomorphic method.
Isolate* isolate = masm->isolate();
Label slow, non_function, wrap, cont;
- int argc = argc_;
StackArgumentsAccessor args(rsp, argc);
- if (NeedsChecks()) {
+ if (needs_checks) {
// Check that the function really is a JavaScript function.
__ JumpIfSmi(rdi, &non_function);
@@ -2249,15 +2250,15 @@
// Fast-case: Just invoke the function.
ParameterCount actual(argc);
- if (CallAsMethod()) {
- if (NeedsChecks()) {
+ if (call_as_method) {
+ if (needs_checks) {
EmitContinueIfStrictOrNative(masm, &cont);
}
// Load the receiver from the stack.
__ movp(rax, args.GetReceiverOperand());
- if (NeedsChecks()) {
+ if (needs_checks) {
__ JumpIfSmi(rax, &wrap);
__ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
@@ -2271,19 +2272,24 @@
__ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper());
- if (NeedsChecks()) {
+ if (needs_checks) {
// Slow-case: Non-function called.
__ bind(&slow);
EmitSlowCase(isolate, masm, &args, argc, &non_function);
}
- if (CallAsMethod()) {
+ if (call_as_method) {
__ bind(&wrap);
EmitWrapCase(masm, &args, &cont);
}
}
+void CallFunctionStub::Generate(MacroAssembler* masm) {
+ CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod());
+}
+
+
void CallConstructStub::Generate(MacroAssembler* masm) {
// rax : number of arguments
// rbx : feedback vector
@@ -2358,6 +2364,54 @@
}
+void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) {
+ // rdi - function
+ // rbx - feedback vector
+ // rdx - slot id (as integer)
+ __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx);
+ __ cmpq(rdi, rcx);
+ __ j(not_equal, miss);
+
+ __ movq(rax, Immediate(arg_count()));
+ __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size,
+ FixedArray::kHeaderSize));
+
+ // Verify that ecx contains an AllocationSite
+ __ AssertUndefinedOrAllocationSite(rbx);
+ ArrayConstructorStub stub(masm->isolate(), arg_count());
+ __ TailCallStub(&stub);
+}
+
+
+void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) {
+ // rdi - function
+ // rbx - feedback vector
+ // rdx - slot id
+ Label miss;
+
+ __ SmiToInteger32(rdx, rdx);
+
+ if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) {
+ Generate_MonomorphicArray(masm, &miss);
+ } else {
+ // So far there is only one customer for our custom feedback scheme.
+ UNREACHABLE();
+ }
+
+ __ bind(&miss);
+ GenerateMiss(masm);
+
+ // The slow case, we need this no matter what to complete a call after a miss.
+ CallFunctionNoFeedback(masm,
+ arg_count(),
+ true,
+ CallAsMethod());
+
+ // Unreachable.
+ __ int3();
+}
+
+
void CallICStub::Generate(MacroAssembler* masm) {
// rdi - function
// rbx - vector
@@ -2372,6 +2426,11 @@
EmitLoadTypeFeedbackVector(masm, rbx);
+ if (state_.stub_type() != CallIC::DEFAULT) {
+ Generate_CustomFeedbackCall(masm);
+ return;
+ }
+
// The checks. First, does rdi match the recorded monomorphic target?
__ SmiToInteger32(rdx, rdx);
__ cmpq(rdi, FieldOperand(rbx, rdx, times_pointer_size,
diff --git a/src/x64/debug-x64.cc b/src/x64/debug-x64.cc
index 6e0e05f..29e176f 100644
--- a/src/x64/debug-x64.cc
+++ b/src/x64/debug-x64.cc
@@ -146,7 +146,7 @@
// jumping to the target address intended by the caller and that was
// overwritten by the address of DebugBreakXXX.
ExternalReference after_break_target =
- ExternalReference(Debug_Address::AfterBreakTarget(), masm->isolate());
+ ExternalReference::debug_after_break_target_address(masm->isolate());
__ Move(kScratchRegister, after_break_target);
__ Jump(Operand(kScratchRegister, 0));
}
@@ -285,8 +285,8 @@
void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
ExternalReference restarter_frame_function_slot =
- ExternalReference(Debug_Address::RestarterFrameFunctionPointer(),
- masm->isolate());
+ ExternalReference::debug_restarter_frame_function_pointer_address(
+ masm->isolate());
__ Move(rax, restarter_frame_function_slot);
__ movp(Operand(rax, 0), Immediate(0));
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 1d1da3d..8a5f09a 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -3024,15 +3024,11 @@
void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
LOperand* key = instr->key();
- int base_offset = instr->is_fixed_typed_array()
- ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
- : 0;
Operand operand(BuildFastArrayOperand(
instr->elements(),
key,
elements_kind,
- base_offset,
- instr->additional_index()));
+ instr->base_offset()));
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
@@ -3098,14 +3094,11 @@
XMMRegister result(ToDoubleRegister(instr->result()));
LOperand* key = instr->key();
if (instr->hydrogen()->RequiresHoleCheck()) {
- int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
- sizeof(kHoleNanLower32);
Operand hole_check_operand = BuildFastArrayOperand(
instr->elements(),
key,
FAST_DOUBLE_ELEMENTS,
- offset,
- instr->additional_index());
+ instr->base_offset() + sizeof(kHoleNanLower32));
__ cmpl(hole_check_operand, Immediate(kHoleNanUpper32));
DeoptimizeIf(equal, instr->environment());
}
@@ -3114,8 +3107,7 @@
instr->elements(),
key,
FAST_DOUBLE_ELEMENTS,
- FixedDoubleArray::kHeaderSize - kHeapObjectTag,
- instr->additional_index());
+ instr->base_offset());
__ movsd(result, double_load_operand);
}
@@ -3125,8 +3117,8 @@
Register result = ToRegister(instr->result());
LOperand* key = instr->key();
bool requires_hole_check = hinstr->RequiresHoleCheck();
- int offset = FixedArray::kHeaderSize - kHeapObjectTag;
Representation representation = hinstr->representation();
+ int offset = instr->base_offset();
if (representation.IsInteger32() && SmiValuesAre32Bits() &&
hinstr->elements_kind() == FAST_SMI_ELEMENTS) {
@@ -3137,8 +3129,7 @@
BuildFastArrayOperand(instr->elements(),
key,
FAST_ELEMENTS,
- offset,
- instr->additional_index()),
+ offset),
Representation::Smi());
__ AssertSmi(scratch);
}
@@ -3152,8 +3143,7 @@
BuildFastArrayOperand(instr->elements(),
key,
FAST_ELEMENTS,
- offset,
- instr->additional_index()),
+ offset),
representation);
// Check for the hole value.
@@ -3184,8 +3174,7 @@
LOperand* elements_pointer,
LOperand* key,
ElementsKind elements_kind,
- uint32_t offset,
- uint32_t additional_index) {
+ uint32_t offset) {
Register elements_pointer_reg = ToRegister(elements_pointer);
int shift_size = ElementsKindToShiftSize(elements_kind);
if (key->IsConstantOperand()) {
@@ -3194,14 +3183,13 @@
Abort(kArrayIndexConstantValueTooBig);
}
return Operand(elements_pointer_reg,
- ((constant_value + additional_index) << shift_size)
- + offset);
+ (constant_value << shift_size) + offset);
} else {
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
return Operand(elements_pointer_reg,
ToRegister(key),
scale_factor,
- offset + (additional_index << shift_size));
+ offset);
}
}
@@ -4184,15 +4172,11 @@
void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
LOperand* key = instr->key();
- int base_offset = instr->is_fixed_typed_array()
- ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
- : 0;
Operand operand(BuildFastArrayOperand(
instr->elements(),
key,
elements_kind,
- base_offset,
- instr->additional_index()));
+ instr->base_offset()));
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
@@ -4264,8 +4248,7 @@
instr->elements(),
key,
FAST_DOUBLE_ELEMENTS,
- FixedDoubleArray::kHeaderSize - kHeapObjectTag,
- instr->additional_index());
+ instr->base_offset());
__ movsd(double_store_operand, value);
}
@@ -4274,7 +4257,7 @@
void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
HStoreKeyed* hinstr = instr->hydrogen();
LOperand* key = instr->key();
- int offset = FixedArray::kHeaderSize - kHeapObjectTag;
+ int offset = instr->base_offset();
Representation representation = hinstr->value()->representation();
if (representation.IsInteger32() && SmiValuesAre32Bits()) {
@@ -4286,8 +4269,7 @@
BuildFastArrayOperand(instr->elements(),
key,
FAST_ELEMENTS,
- offset,
- instr->additional_index()),
+ offset),
Representation::Smi());
__ AssertSmi(scratch);
}
@@ -4301,9 +4283,7 @@
BuildFastArrayOperand(instr->elements(),
key,
FAST_ELEMENTS,
- offset,
- instr->additional_index());
-
+ offset);
if (instr->value()->IsRegister()) {
__ Store(operand, ToRegister(instr->value()), representation);
} else {
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index 686dc85..0879b95 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -225,8 +225,7 @@
LOperand* elements_pointer,
LOperand* key,
ElementsKind elements_kind,
- uint32_t offset,
- uint32_t additional_index = 0);
+ uint32_t base_offset);
Operand BuildSeqStringOperand(Register string,
LOperand* index,
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index cbade8a..ec677ee 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -371,7 +371,7 @@
stream->Add("[");
key()->PrintTo(stream);
if (hydrogen()->IsDehoisted()) {
- stream->Add(" + %d]", additional_index());
+ stream->Add(" + %d]", base_offset());
} else {
stream->Add("]");
}
@@ -383,7 +383,7 @@
stream->Add("[");
key()->PrintTo(stream);
if (hydrogen()->IsDehoisted()) {
- stream->Add(" + %d] <-", additional_index());
+ stream->Add(" + %d] <-", base_offset());
} else {
stream->Add("] <- ");
}
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 86121f6..e3db375 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -1628,7 +1628,7 @@
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- uint32_t additional_index() const { return hydrogen()->index_offset(); }
+ uint32_t base_offset() const { return hydrogen()->base_offset(); }
ElementsKind elements_kind() const {
return hydrogen()->elements_kind();
}
@@ -2184,7 +2184,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
- uint32_t additional_index() const { return hydrogen()->index_offset(); }
+ uint32_t base_offset() const { return hydrogen()->base_offset(); }
};
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 1292628..e655749 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -205,7 +205,7 @@
},
{
'dependencies': [
- '../../tools/gyp/v8.gyp:v8_nosnapshot.<(v8_target_arch)',
+ '../../tools/gyp/v8.gyp:v8_nosnapshot',
],
}],
],
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 1d790a1..e2f7462 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -10282,7 +10282,7 @@
// Getting property names of an object with a prototype chain that
-// triggers dictionary elements in GetLocalPropertyNames() shouldn't
+// triggers dictionary elements in GetOwnPropertyNames() shouldn't
// crash the runtime.
THREADED_TEST(Regress91517) {
i::FLAG_allow_natives_syntax = true;
@@ -10321,11 +10321,11 @@
CHECK(o3->SetPrototype(o2));
CHECK(o2->SetPrototype(o1));
- // Call the runtime version of GetLocalPropertyNames() on the natively
+ // Call the runtime version of GetOwnPropertyNames() on the natively
// created object through JavaScript.
context->Global()->Set(v8_str("obj"), o4);
// PROPERTY_ATTRIBUTES_NONE = 0
- CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
+ CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
ExpectInt32("names.length", 1006);
ExpectTrue("names.indexOf(\"baz\") >= 0");
@@ -10376,12 +10376,12 @@
o1->SetHiddenValue(
v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));
- // Call the runtime version of GetLocalPropertyNames() on
+ // Call the runtime version of GetOwnPropertyNames() on
// the natively created object through JavaScript.
context->Global()->Set(v8_str("obj"), o2);
context->Global()->Set(v8_str("sym"), sym);
// PROPERTY_ATTRIBUTES_NONE = 0
- CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
+ CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
ExpectInt32("names.length", 7);
ExpectTrue("names.indexOf(\"foo\") >= 0");
@@ -13514,7 +13514,6 @@
static int GetGlobalObjectsCount() {
- CcTest::heap()->EnsureHeapIsIterable();
int count = 0;
i::HeapIterator it(CcTest::heap());
for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
@@ -19252,7 +19251,7 @@
ExpectUndefined("Object.prototype.__lookupGetter__.call("
" other, \'x\')");
- // HasLocalElement.
+ // HasOwnElement.
ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
CHECK_EQ(false, global0->HasRealIndexedProperty(0));
@@ -21686,13 +21685,13 @@
CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
- CheckCorrectThrow("%HasLocalProperty(other, 'x')");
+ CheckCorrectThrow("%HasOwnProperty(other, 'x')");
CheckCorrectThrow("%HasProperty(other, 'x')");
CheckCorrectThrow("%HasElement(other, 1)");
CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
CheckCorrectThrow("%GetPropertyNames(other)");
// PROPERTY_ATTRIBUTES_NONE = 0
- CheckCorrectThrow("%GetLocalPropertyNames(other, 0)");
+ CheckCorrectThrow("%GetOwnPropertyNames(other, 0)");
CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
"other, 'x', null, null, 1)");
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 52e0fd6..ce422b5 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -587,6 +587,72 @@
}
+static const char* hot_deopt_no_frame_entry_test_source =
+"function foo(a, b) {\n"
+" try {\n"
+" return a + b;\n"
+" } catch (e) { }\n"
+"}\n"
+"function start(timeout) {\n"
+" var start = Date.now();\n"
+" do {\n"
+" for (var i = 1; i < 1000; ++i) foo(1, i);\n"
+" var duration = Date.now() - start;\n"
+" } while (duration < timeout);\n"
+" return duration;\n"
+"}\n";
+
+// Check that the profile tree for the script above will look like the
+// following:
+//
+// [Top down]:
+// 1062 0 (root) [-1]
+// 1054 0 start [-1]
+// 1054 1 foo [-1]
+// 2 2 (program) [-1]
+// 6 6 (garbage collector) [-1]
+//
+// The test checks no FP ranges are present in a deoptimized funcion.
+// If 'foo' has no ranges the samples falling into the prologue will miss the
+// 'start' function on the stack, so 'foo' will be attached to the (root).
+TEST(HotDeoptNoFrameEntry) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+
+ v8::Script::Compile(v8::String::NewFromUtf8(
+ env->GetIsolate(),
+ hot_deopt_no_frame_entry_test_source))->Run();
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
+
+ int32_t profiling_interval_ms = 200;
+ v8::Handle<v8::Value> args[] = {
+ v8::Integer::New(env->GetIsolate(), profiling_interval_ms)
+ };
+ v8::CpuProfile* profile =
+ RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 200);
+ function->Call(env->Global(), ARRAY_SIZE(args), args);
+
+ const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+
+ ScopedVector<v8::Handle<v8::String> > names(3);
+ names[0] = v8::String::NewFromUtf8(
+ env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
+ names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
+ ProfileGenerator::kProgramEntryName);
+ names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
+ CheckChildrenNames(root, names);
+
+ const v8::CpuProfileNode* startNode =
+ GetChild(env->GetIsolate(), root, "start");
+ CHECK_EQ(1, startNode->GetChildrenCount());
+
+ GetChild(env->GetIsolate(), startNode, "foo");
+
+ profile->Delete();
+}
+
+
TEST(CollectCpuProfileSamples) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index b369e83..9b1fd5d 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -275,7 +275,7 @@
__ jmp(&L1);
__ jmp(Operand(ebx, ecx, times_4, 10000));
ExternalReference after_break_target =
- ExternalReference(Debug_Address::AfterBreakTarget(), isolate);
+ ExternalReference::debug_after_break_target_address(isolate);
__ jmp(Operand::StaticVariable(after_break_target));
__ jmp(ic, RelocInfo::CODE_TARGET);
__ nop();
diff --git a/test/cctest/test-disasm-x64.cc b/test/cctest/test-disasm-x64.cc
index 3b1f8af..9a17dd1 100644
--- a/test/cctest/test-disasm-x64.cc
+++ b/test/cctest/test-disasm-x64.cc
@@ -261,7 +261,7 @@
// TODO(mstarzinger): The following is protected.
// __ jmp(Operand(rbx, rcx, times_4, 10000));
ExternalReference after_break_target =
- ExternalReference(Debug_Address::AfterBreakTarget(), isolate);
+ ExternalReference::debug_after_break_target_address(isolate);
USE(after_break_target);
__ jmp(ic, RelocInfo::CODE_TARGET);
__ nop();
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index 0417ace..dbef127 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -471,6 +471,29 @@
}
+TEST(HeapSnapshotSymbol) {
+ i::FLAG_harmony_symbols = true;
+
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+
+ CompileRun("a = Symbol('mySymbol');\n");
+ const v8::HeapSnapshot* snapshot =
+ heap_profiler->TakeHeapSnapshot(v8_str("Symbol"));
+ CHECK(ValidateSnapshot(snapshot));
+ const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+ const v8::HeapGraphNode* a =
+ GetProperty(global, v8::HeapGraphEdge::kProperty, "a");
+ CHECK_NE(NULL, a);
+ CHECK_EQ(a->GetType(), v8::HeapGraphNode::kSymbol);
+ CHECK_EQ(v8_str("symbol"), a->GetName());
+ const v8::HeapGraphNode* name =
+ GetProperty(a, v8::HeapGraphEdge::kInternal, "name");
+ CHECK_NE(NULL, name);
+ CHECK_EQ(v8_str("mySymbol"), name->GetName());
+}
+
TEST(HeapSnapshotInternalReferences) {
v8::Isolate* isolate = CcTest::isolate();
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 45ec1fc..f797ecc 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -209,7 +209,7 @@
Handle<String> object_string = Handle<String>::cast(factory->Object_string());
Handle<GlobalObject> global(CcTest::i_isolate()->context()->global_object());
- CHECK(JSReceiver::HasLocalProperty(global, object_string));
+ CHECK(JSReceiver::HasOwnProperty(global, object_string));
// Check ToString for oddballs
CheckOddball(isolate, heap->true_value(), "true");
@@ -278,7 +278,7 @@
heap->CollectGarbage(NEW_SPACE);
// Function should be alive.
- CHECK(JSReceiver::HasLocalProperty(global, name));
+ CHECK(JSReceiver::HasOwnProperty(global, name));
// Check function is retained.
Handle<Object> func_value =
Object::GetProperty(global, name).ToHandleChecked();
@@ -297,7 +297,7 @@
// After gc, it should survive.
heap->CollectGarbage(NEW_SPACE);
- CHECK(JSReceiver::HasLocalProperty(global, obj_name));
+ CHECK(JSReceiver::HasOwnProperty(global, obj_name));
Handle<Object> obj =
Object::GetProperty(global, obj_name).ToHandleChecked();
CHECK(obj->IsJSObject());
@@ -655,55 +655,55 @@
Handle<Smi> two(Smi::FromInt(2), isolate);
// check for empty
- CHECK(!JSReceiver::HasLocalProperty(obj, first));
+ CHECK(!JSReceiver::HasOwnProperty(obj, first));
// add first
JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY).Check();
- CHECK(JSReceiver::HasLocalProperty(obj, first));
+ CHECK(JSReceiver::HasOwnProperty(obj, first));
// delete first
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
- CHECK(!JSReceiver::HasLocalProperty(obj, first));
+ CHECK(!JSReceiver::HasOwnProperty(obj, first));
// add first and then second
JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY).Check();
JSReceiver::SetProperty(obj, second, two, NONE, SLOPPY).Check();
- CHECK(JSReceiver::HasLocalProperty(obj, first));
- CHECK(JSReceiver::HasLocalProperty(obj, second));
+ CHECK(JSReceiver::HasOwnProperty(obj, first));
+ CHECK(JSReceiver::HasOwnProperty(obj, second));
// delete first and then second
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
- CHECK(JSReceiver::HasLocalProperty(obj, second));
+ CHECK(JSReceiver::HasOwnProperty(obj, second));
JSReceiver::DeleteProperty(obj, second, JSReceiver::NORMAL_DELETION).Check();
- CHECK(!JSReceiver::HasLocalProperty(obj, first));
- CHECK(!JSReceiver::HasLocalProperty(obj, second));
+ CHECK(!JSReceiver::HasOwnProperty(obj, first));
+ CHECK(!JSReceiver::HasOwnProperty(obj, second));
// add first and then second
JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY).Check();
JSReceiver::SetProperty(obj, second, two, NONE, SLOPPY).Check();
- CHECK(JSReceiver::HasLocalProperty(obj, first));
- CHECK(JSReceiver::HasLocalProperty(obj, second));
+ CHECK(JSReceiver::HasOwnProperty(obj, first));
+ CHECK(JSReceiver::HasOwnProperty(obj, second));
// delete second and then first
JSReceiver::DeleteProperty(obj, second, JSReceiver::NORMAL_DELETION).Check();
- CHECK(JSReceiver::HasLocalProperty(obj, first));
+ CHECK(JSReceiver::HasOwnProperty(obj, first));
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
- CHECK(!JSReceiver::HasLocalProperty(obj, first));
- CHECK(!JSReceiver::HasLocalProperty(obj, second));
+ CHECK(!JSReceiver::HasOwnProperty(obj, first));
+ CHECK(!JSReceiver::HasOwnProperty(obj, second));
// check string and internalized string match
const char* string1 = "fisk";
Handle<String> s1 = factory->NewStringFromAsciiChecked(string1);
JSReceiver::SetProperty(obj, s1, one, NONE, SLOPPY).Check();
Handle<String> s1_string = factory->InternalizeUtf8String(string1);
- CHECK(JSReceiver::HasLocalProperty(obj, s1_string));
+ CHECK(JSReceiver::HasOwnProperty(obj, s1_string));
// check internalized string and string match
const char* string2 = "fugl";
Handle<String> s2_string = factory->InternalizeUtf8String(string2);
JSReceiver::SetProperty(obj, s2_string, one, NONE, SLOPPY).Check();
Handle<String> s2 = factory->NewStringFromAsciiChecked(string2);
- CHECK(JSReceiver::HasLocalProperty(obj, s2));
+ CHECK(JSReceiver::HasOwnProperty(obj, s2));
}
@@ -890,7 +890,6 @@
static int ObjectsFoundInHeap(Heap* heap, Handle<Object> objs[], int size) {
// Count the number of objects found in the heap.
int found_count = 0;
- heap->EnsureHeapIsIterable();
HeapIterator iterator(heap);
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
for (int i = 0; i < size; i++) {
@@ -1629,9 +1628,8 @@
TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
CcTest::InitializeVM();
- CcTest::heap()->EnsureHeapIsIterable();
- intptr_t size_of_objects_1 = CcTest::heap()->SizeOfObjects();
HeapIterator iterator(CcTest::heap());
+ intptr_t size_of_objects_1 = CcTest::heap()->SizeOfObjects();
intptr_t size_of_objects_2 = 0;
for (HeapObject* obj = iterator.next();
obj != NULL;
diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc
index 08b1c71..529bd242 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -166,7 +166,7 @@
{ HandleScope scope(isolate);
Handle<String> func_name = factory->InternalizeUtf8String("theFunction");
- CHECK(JSReceiver::HasLocalProperty(global, func_name));
+ CHECK(JSReceiver::HasOwnProperty(global, func_name));
Handle<Object> func_value =
Object::GetProperty(global, func_name).ToHandleChecked();
CHECK(func_value->IsJSFunction());
@@ -184,7 +184,7 @@
{ HandleScope scope(isolate);
Handle<String> obj_name = factory->InternalizeUtf8String("theObject");
- CHECK(JSReceiver::HasLocalProperty(global, obj_name));
+ CHECK(JSReceiver::HasOwnProperty(global, obj_name));
Handle<Object> object =
Object::GetProperty(global, obj_name).ToHandleChecked();
CHECK(object->IsJSObject());
diff --git a/test/cctest/test-object-observe.cc b/test/cctest/test-object-observe.cc
index a7b346f..7c78932 100644
--- a/test/cctest/test-object-observe.cc
+++ b/test/cctest/test-object-observe.cc
@@ -616,7 +616,6 @@
static int GetGlobalObjectsCount() {
- CcTest::heap()->EnsureHeapIsIterable();
int count = 0;
i::HeapIterator it(CcTest::heap());
for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 10c35c1..59ce2da 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -262,7 +262,7 @@
// Test that the whole heap can be serialized.
TEST(Serialize) {
if (!Snapshot::HaveASnapshotToStartFrom()) {
- Serializer::RequestEnable(CcTest::i_isolate());
+ CcTest::i_isolate()->enable_serializer();
v8::V8::Initialize();
Serialize();
}
@@ -272,7 +272,7 @@
// Test that heap serialization is non-destructive.
TEST(SerializeTwice) {
if (!Snapshot::HaveASnapshotToStartFrom()) {
- Serializer::RequestEnable(CcTest::i_isolate());
+ CcTest::i_isolate()->enable_serializer();
v8::V8::Initialize();
Serialize();
Serialize();
@@ -370,7 +370,7 @@
TEST(PartialSerialization) {
if (!Snapshot::HaveASnapshotToStartFrom()) {
Isolate* isolate = CcTest::i_isolate();
- Serializer::RequestEnable(isolate);
+ CcTest::i_isolate()->enable_serializer();
v8::V8::Initialize();
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
Heap* heap = isolate->heap();
@@ -521,7 +521,7 @@
TEST(ContextSerialization) {
if (!Snapshot::HaveASnapshotToStartFrom()) {
Isolate* isolate = CcTest::i_isolate();
- Serializer::RequestEnable(isolate);
+ CcTest::i_isolate()->enable_serializer();
v8::V8::Initialize();
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
Heap* heap = isolate->heap();
diff --git a/test/mjsunit/array-constructor-feedback.js b/test/mjsunit/array-constructor-feedback.js
index 45d5c58..9bc62e4 100644
--- a/test/mjsunit/array-constructor-feedback.js
+++ b/test/mjsunit/array-constructor-feedback.js
@@ -150,18 +150,11 @@
a = bar(10);
assertKind(elements_kind.fast, a);
assertOptimized(bar);
- // bar should deopt because the length is too large.
- a = bar(100000);
- assertUnoptimized(bar);
- assertKind(elements_kind.dictionary, a);
- // The allocation site now has feedback that means the array constructor
- // will not be inlined.
- %OptimizeFunctionOnNextCall(bar);
a = bar(100000);
assertKind(elements_kind.dictionary, a);
assertOptimized(bar);
- // If the argument isn't a smi, it bails out as well
+ // If the argument isn't a smi, things should still work.
a = bar("oops");
assertOptimized(bar);
assertKind(elements_kind.fast, a);
@@ -176,12 +169,6 @@
barn(1, 2, 3);
assertOptimized(barn);
a = barn(1, "oops", 3);
- // The method should deopt, but learn from the failure to avoid inlining
- // the array.
- assertKind(elements_kind.fast, a);
- assertUnoptimized(barn);
- %OptimizeFunctionOnNextCall(barn);
- a = barn(1, "oops", 3);
assertOptimized(barn);
})();
@@ -228,10 +215,8 @@
assertTrue(Realm.eval(contextB, "bar2() instanceof Array"));
})();
- // Test: create array with packed feedback, then optimize/inline
- // function. Verify that if we ask for a holey array then we deopt.
- // Reoptimization will proceed with the correct feedback and we
- // won't deopt anymore.
+ // Test: create array with packed feedback, then optimize function, which
+ // should deal with arguments that create holey arrays.
(function() {
function bar(len) { return new Array(len); }
bar(0);
@@ -241,15 +226,16 @@
assertOptimized(bar);
assertFalse(isHoley(a));
a = bar(1); // ouch!
- assertUnoptimized(bar);
- assertTrue(isHoley(a));
- // Try again
- %OptimizeFunctionOnNextCall(bar);
- a = bar(100);
assertOptimized(bar);
assertTrue(isHoley(a));
+ a = bar(100);
+ assertTrue(isHoley(a));
a = bar(0);
assertOptimized(bar);
- assertTrue(isHoley(a));
+ // Crankshafted functions don't use mementos, so feedback still
+ // indicates a packed array is desired. (unless --nocrankshaft is in use).
+ if (4 != %GetOptimizationStatus(bar)) {
+ assertFalse(isHoley(a));
+ }
})();
}
diff --git a/test/mjsunit/array-feedback.js b/test/mjsunit/array-feedback.js
index 4129be1..cb91995 100644
--- a/test/mjsunit/array-feedback.js
+++ b/test/mjsunit/array-feedback.js
@@ -85,69 +85,69 @@
// Verify that basic elements kind feedback works for non-constructor
// array calls (as long as the call is made through an IC, and not
// a CallStub).
- // (function (){
- // function create0() {
- // return Array();
- // }
+ (function (){
+ function create0() {
+ return Array();
+ }
- // // Calls through ICs need warm up through uninitialized, then
- // // premonomorphic first.
- // create0();
- // create0();
- // a = create0();
- // assertKind(elements_kind.fast_smi_only, a);
- // a[0] = 3.5;
- // b = create0();
- // assertKind(elements_kind.fast_double, b);
+ // Calls through ICs need warm up through uninitialized, then
+ // premonomorphic first.
+ create0();
+ a = create0();
+ assertKind(elements_kind.fast_smi_only, a);
+ a[0] = 3.5;
+ b = create0();
+ assertKind(elements_kind.fast_double, b);
- // function create1(arg) {
- // return Array(arg);
- // }
+ function create1(arg) {
+ return Array(arg);
+ }
- // create1(0);
- // create1(0);
- // a = create1(0);
- // assertFalse(isHoley(a));
- // assertKind(elements_kind.fast_smi_only, a);
- // a[0] = "hello";
- // b = create1(10);
- // assertTrue(isHoley(b));
- // assertKind(elements_kind.fast, b);
+ create1(0);
+ create1(0);
+ a = create1(0);
+ assertFalse(isHoley(a));
+ assertKind(elements_kind.fast_smi_only, a);
+ a[0] = "hello";
+ b = create1(10);
+ assertTrue(isHoley(b));
+ assertKind(elements_kind.fast, b);
- // a = create1(100000);
- // assertKind(elements_kind.dictionary, a);
+ a = create1(100000);
+ assertKind(elements_kind.dictionary, a);
- // function create3(arg1, arg2, arg3) {
- // return Array(arg1, arg2, arg3);
- // }
+ function create3(arg1, arg2, arg3) {
+ return Array(arg1, arg2, arg3);
+ }
- // create3();
- // create3();
- // a = create3(1,2,3);
- // a[0] = 3.5;
- // b = create3(1,2,3);
- // assertKind(elements_kind.fast_double, b);
- // assertFalse(isHoley(b));
- // })();
+ create3(1,2,3);
+ create3(1,2,3);
+ a = create3(1,2,3);
+ a[0] = 3.035;
+ assertKind(elements_kind.fast_double, a);
+ b = create3(1,2,3);
+ assertKind(elements_kind.fast_double, b);
+ assertFalse(isHoley(b));
+ })();
// Verify that keyed calls work
- // (function (){
- // function create0(name) {
- // return this[name]();
- // }
+ (function (){
+ function create0(name) {
+ return this[name]();
+ }
- // name = "Array";
- // create0(name);
- // create0(name);
- // a = create0(name);
- // a[0] = 3.5;
- // b = create0(name);
- // assertKind(elements_kind.fast_double, b);
- // })();
+ name = "Array";
+ create0(name);
+ create0(name);
+ a = create0(name);
+ a[0] = 3.5;
+ b = create0(name);
+ assertKind(elements_kind.fast_double, b);
+ })();
- // Verify that the IC can't be spoofed by patching
+ // Verify that crankshaft consumes type feedback.
(function (){
function create0() {
return Array();
@@ -156,42 +156,41 @@
create0();
create0();
a = create0();
- assertKind(elements_kind.fast_smi_only, a);
- var oldArray = this.Array;
- this.Array = function() { return ["hi"]; };
+ a[0] = 3.5;
+ %OptimizeFunctionOnNextCall(create0);
+ create0();
+ create0();
b = create0();
- assertEquals(["hi"], b);
- this.Array = oldArray;
+ assertKind(elements_kind.fast_double, b);
+ assertOptimized(create0);
+
+ function create1(arg) {
+ return Array(arg);
+ }
+
+ create1(8);
+ create1(8);
+ a = create1(8);
+ a[0] = 3.5;
+ %OptimizeFunctionOnNextCall(create1);
+ b = create1(8);
+ assertKind(elements_kind.fast_double, b);
+ assertOptimized(create1);
+
+ function createN(arg1, arg2, arg3) {
+ return Array(arg1, arg2, arg3);
+ }
+
+ createN(1, 2, 3);
+ createN(1, 2, 3);
+ a = createN(1, 2, 3);
+ a[0] = 3.5;
+ %OptimizeFunctionOnNextCall(createN);
+ b = createN(1, 2, 3);
+ assertKind(elements_kind.fast_double, b);
+ assertOptimized(createN);
})();
- // Verify that calls are still made through an IC after crankshaft,
- // though the type information is reset.
- // TODO(mvstanton): instead, consume the type feedback gathered up
- // until crankshaft time.
- // (function (){
- // function create0() {
- // return Array();
- // }
-
- // create0();
- // create0();
- // a = create0();
- // a[0] = 3.5;
- // %OptimizeFunctionOnNextCall(create0);
- // create0();
- // // This test only makes sense if crankshaft is allowed
- // if (4 != %GetOptimizationStatus(create0)) {
- // create0();
- // b = create0();
- // assertKind(elements_kind.fast_smi_only, b);
- // b[0] = 3.5;
- // c = create0();
- // assertKind(elements_kind.fast_double, c);
- // assertOptimized(create0);
- // }
- // })();
-
-
// Verify that cross context calls work
(function (){
var realmA = Realm.current();
diff --git a/test/mjsunit/array-push-unshift-read-only-length.js b/test/mjsunit/array-push-unshift-read-only-length.js
new file mode 100644
index 0000000..67aa397
--- /dev/null
+++ b/test/mjsunit/array-push-unshift-read-only-length.js
@@ -0,0 +1,107 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function test(mode) {
+ var a = [];
+ Object.defineProperty(a, "length", { writable : false});
+
+ function check(f) {
+ try {
+ f(a);
+ } catch(e) { }
+ assertFalse(0 in a);
+ assertEquals(0, a.length);
+ }
+
+ function push(a) {
+ a.push(3);
+ }
+
+ if (mode == "fast properties") %ToFastProperties(a);
+
+ check(push);
+ check(push);
+ check(push);
+ %OptimizeFunctionOnNextCall(push);
+ check(push);
+
+ function unshift(a) {
+ a.unshift(3);
+ }
+
+ check(unshift);
+ check(unshift);
+ check(unshift);
+ %OptimizeFunctionOnNextCall(unshift);
+ check(unshift);
+}
+
+test("fast properties");
+
+test("normalized");
+
+var b = [];
+Object.defineProperty(b.__proto__, "0", {
+ set : function(v) {
+ b.x = v;
+ Object.defineProperty(b, "length", { writable : false });
+ },
+ get: function() {
+ return b.x;
+ }
+});
+
+b = [];
+try {
+ b.push(3, 4, 5);
+} catch(e) { }
+assertFalse(1 in b);
+assertFalse(2 in b);
+assertEquals(0, b.length);
+
+b = [];
+try {
+ b.unshift(3, 4, 5);
+} catch(e) { }
+assertFalse(1 in b);
+assertFalse(2 in b);
+assertEquals(0, b.length);
+
+b = [1, 2];
+try {
+ b.unshift(3, 4, 5);
+} catch(e) { }
+assertEquals(3, b[0]);
+assertEquals(4, b[1]);
+assertEquals(5, b[2]);
+assertEquals(1, b[3]);
+assertEquals(2, b[4]);
+assertEquals(5, b.length);
+
+b = [1, 2];
+
+Object.defineProperty(b.__proto__, "4", {
+ set : function(v) {
+ b.z = v;
+ Object.defineProperty(b, "length", { writable : false });
+ },
+ get: function() {
+ return b.z;
+ }
+});
+
+try {
+ b.unshift(3, 4, 5);
+} catch(e) { }
+
+// TODO(ulan): According to the ECMA-262 unshift should throw an exception
+// when moving b[0] to b[3] (see 15.4.4.13 step 6.d.ii). This is difficult
+// to do with our current implementation of SmartMove() in src/array.js and
+// it will regress performance. Uncomment the following line once acceptable
+// solution is found:
+// assertFalse(2 in b);
+// assertFalse(3 in b);
+// assertEquals(2, b.length);
diff --git a/test/mjsunit/harmony/generators-debug-liveedit.js b/test/mjsunit/harmony/generators-debug-liveedit.js
new file mode 100644
index 0000000..341ef48
--- /dev/null
+++ b/test/mjsunit/harmony/generators-debug-liveedit.js
@@ -0,0 +1,119 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --harmony-generators
+
+var Debug = debug.Debug;
+var LiveEdit = Debug.LiveEdit;
+
+unique_id = 0;
+
+var Generator = (function*(){}).constructor;
+
+function assertIteratorResult(value, done, result) {
+ assertEquals({value: value, done: done}, result);
+}
+
+function MakeGenerator() {
+ // Prevents eval script caching.
+ unique_id++;
+ return Generator('callback',
+ "/* " + unique_id + "*/\n" +
+ "yield callback();\n" +
+ "return 'Cat';\n");
+}
+
+function MakeFunction() {
+ // Prevents eval script caching.
+ unique_id++;
+ return Function('callback',
+ "/* " + unique_id + "*/\n" +
+ "callback();\n" +
+ "return 'Cat';\n");
+}
+
+// First, try MakeGenerator with no perturbations.
+(function(){
+ var generator = MakeGenerator();
+ function callback() {};
+ var iter = generator(callback);
+ assertIteratorResult(undefined, false, iter.next());
+ assertIteratorResult("Cat", true, iter.next());
+})();
+
+function patch(fun, from, to) {
+ function debug() {
+ var log = new Array();
+ var script = Debug.findScript(fun);
+ var pos = script.source.indexOf(from);
+ try {
+ LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to,
+ log);
+ } finally {
+ print("Change log: " + JSON.stringify(log) + "\n");
+ }
+ }
+ Debug.ExecuteInDebugContext(debug, false);
+}
+
+// Try to edit a MakeGenerator while it's running, then again while it's
+// stopped.
+(function(){
+ var generator = MakeGenerator();
+
+ var gen_patch_attempted = false;
+ function attempt_gen_patch() {
+ assertFalse(gen_patch_attempted);
+ gen_patch_attempted = true;
+ assertThrows(function() { patch(generator, "'Cat'", "'Capybara'") },
+ LiveEdit.Failure);
+ };
+ var iter = generator(attempt_gen_patch);
+ assertIteratorResult(undefined, false, iter.next());
+ // Patch should not succeed because there is a live generator activation on
+ // the stack.
+ assertIteratorResult("Cat", true, iter.next());
+ assertTrue(gen_patch_attempted);
+
+ // At this point one iterator is live, but closed, so the patch will succeed.
+ patch(generator, "'Cat'", "'Capybara'");
+ iter = generator(function(){});
+ assertIteratorResult(undefined, false, iter.next());
+ // Patch successful.
+ assertIteratorResult("Capybara", true, iter.next());
+
+ // Patching will fail however when a live iterator is suspended.
+ iter = generator(function(){});
+ assertIteratorResult(undefined, false, iter.next());
+ assertThrows(function() { patch(generator, "'Capybara'", "'Tapir'") },
+ LiveEdit.Failure);
+ assertIteratorResult("Capybara", true, iter.next());
+
+ // Try to patch functions with activations inside and outside generator
+ // function activations. We should succeed in the former case, but not in the
+ // latter.
+ var fun_outside = MakeFunction();
+ var fun_inside = MakeFunction();
+ var fun_patch_attempted = false;
+ var fun_patch_restarted = false;
+ function attempt_fun_patches() {
+ if (fun_patch_attempted) {
+ assertFalse(fun_patch_restarted);
+ fun_patch_restarted = true;
+ return;
+ }
+ fun_patch_attempted = true;
+ // Patching outside a generator activation must fail.
+ assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") },
+ LiveEdit.Failure);
+ // Patching inside a generator activation may succeed.
+ patch(fun_inside, "'Cat'", "'Koala'");
+ }
+ iter = generator(function() { return fun_inside(attempt_fun_patches) });
+ assertEquals('Cat',
+ fun_outside(function () {
+ assertIteratorResult('Koala', false, iter.next());
+ assertTrue(fun_patch_restarted);
+ }));
+})();
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index e460e7c..2df8747 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -206,6 +206,7 @@
'debug-liveedit-stack-padding': [SKIP],
'debug-liveedit-restart-frame': [SKIP],
'debug-liveedit-double-call': [SKIP],
+ 'harmony/generators-debug-liveedit': [SKIP],
# BUG(v8:3147). It works on other architectures by accident.
'regress/regress-conditional-position': [FAIL],
@@ -302,6 +303,7 @@
'debug-liveedit-stack-padding': [SKIP],
'debug-liveedit-restart-frame': [SKIP],
'debug-liveedit-double-call': [SKIP],
+ 'harmony/generators-debug-liveedit': [SKIP],
# Currently always deopt on minus zero
'math-floor-of-div-minus-zero': [SKIP],
@@ -353,6 +355,7 @@
'debug-liveedit-stack-padding': [SKIP],
'debug-liveedit-restart-frame': [SKIP],
'debug-liveedit-double-call': [SKIP],
+ 'harmony/generators-debug-liveedit': [SKIP],
# Currently always deopt on minus zero
'math-floor-of-div-minus-zero': [SKIP],
@@ -373,6 +376,7 @@
'debug-liveedit-stack-padding': [SKIP],
'debug-liveedit-restart-frame': [SKIP],
'debug-liveedit-double-call': [SKIP],
+ 'harmony/generators-debug-liveedit': [SKIP],
# NaCl builds have problems with this test since Pepper_28.
# V8 Issue 2786
diff --git a/test/mjsunit/regress/regress-373283.js b/test/mjsunit/regress/regress-373283.js
new file mode 100644
index 0000000..20cee4d
--- /dev/null
+++ b/test/mjsunit/regress/regress-373283.js
@@ -0,0 +1,18 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --deopt-every-n-times=1
+
+function __f_0() {
+ var x = [];
+ x[21] = 1;
+ x[21] + 0;
+}
+
+for (var i = 0; i < 3; i++) __f_0();
+%OptimizeFunctionOnNextCall(__f_0);
+for (var i = 0; i < 10; i++) __f_0();
+%OptimizeFunctionOnNextCall(__f_0);
+__f_0();
+%GetScript("foo");
diff --git a/test/mjsunit/runtime-gen/getlocalelementnames.js b/test/mjsunit/runtime-gen/getownelementnames.js
similarity index 87%
rename from test/mjsunit/runtime-gen/getlocalelementnames.js
rename to test/mjsunit/runtime-gen/getownelementnames.js
index cf0447d..3f02cba 100644
--- a/test/mjsunit/runtime-gen/getlocalelementnames.js
+++ b/test/mjsunit/runtime-gen/getownelementnames.js
@@ -2,4 +2,4 @@
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
// Flags: --allow-natives-syntax --harmony
var _obj = new Object();
-%GetLocalElementNames(_obj);
+%GetOwnElementNames(_obj);
diff --git a/test/mjsunit/runtime-gen/getlocalpropertynames.js b/test/mjsunit/runtime-gen/getownpropertynames.js
similarity index 83%
rename from test/mjsunit/runtime-gen/getlocalpropertynames.js
rename to test/mjsunit/runtime-gen/getownpropertynames.js
index 2a93868..f05268f 100644
--- a/test/mjsunit/runtime-gen/getlocalpropertynames.js
+++ b/test/mjsunit/runtime-gen/getownpropertynames.js
@@ -3,4 +3,4 @@
// Flags: --allow-natives-syntax --harmony
var _obj = new Object();
var _filter_value = 1;
-%GetLocalPropertyNames(_obj, _filter_value);
+%GetOwnPropertyNames(_obj, _filter_value);
diff --git a/test/mjsunit/runtime-gen/haslocalproperty.js b/test/mjsunit/runtime-gen/hasownproperty.js
similarity index 86%
rename from test/mjsunit/runtime-gen/haslocalproperty.js
rename to test/mjsunit/runtime-gen/hasownproperty.js
index 066e6d1..7be0a65 100644
--- a/test/mjsunit/runtime-gen/haslocalproperty.js
+++ b/test/mjsunit/runtime-gen/hasownproperty.js
@@ -3,4 +3,4 @@
// Flags: --allow-natives-syntax --harmony
var _object = new Object();
var _key = "name";
-%HasLocalProperty(_object, _key);
+%HasOwnProperty(_object, _key);
diff --git a/test/mjsunit/runtime-gen/localkeys.js b/test/mjsunit/runtime-gen/ownkeys.js
similarity index 89%
rename from test/mjsunit/runtime-gen/localkeys.js
rename to test/mjsunit/runtime-gen/ownkeys.js
index 0186177..7e4220d 100644
--- a/test/mjsunit/runtime-gen/localkeys.js
+++ b/test/mjsunit/runtime-gen/ownkeys.js
@@ -2,4 +2,4 @@
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
// Flags: --allow-natives-syntax --harmony
var _raw_object = new Object();
-%LocalKeys(_raw_object);
+%OwnKeys(_raw_object);
diff --git a/test/mjsunit/tools/tickprocessor-test.default b/test/mjsunit/tools/tickprocessor-test.default
index 702f4bc..8ab17c3 100644
--- a/test/mjsunit/tools/tickprocessor-test.default
+++ b/test/mjsunit/tools/tickprocessor-test.default
@@ -16,7 +16,7 @@
[C++]:
ticks total nonlib name
2 15.4% 22.2% v8::internal::Runtime_Math_exp(v8::internal::Arguments)
- 1 7.7% 11.1% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
+ 1 7.7% 11.1% v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 7.7% 11.1% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
1 7.7% 11.1% exp
@@ -38,7 +38,7 @@
2 100.0% LazyCompile: exp native math.js:41
2 100.0% Script: exp.js
- 1 7.7% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
+ 1 7.7% v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 100.0% Script: exp.js
1 7.7% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
diff --git a/test/mjsunit/tools/tickprocessor-test.ignore-unknown b/test/mjsunit/tools/tickprocessor-test.ignore-unknown
index 306d646..677da9c 100644
--- a/test/mjsunit/tools/tickprocessor-test.ignore-unknown
+++ b/test/mjsunit/tools/tickprocessor-test.ignore-unknown
@@ -12,7 +12,7 @@
[C++]:
ticks total nonlib name
2 18.2% 28.6% v8::internal::Runtime_Math_exp(v8::internal::Arguments)
- 1 9.1% 14.3% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
+ 1 9.1% 14.3% v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 9.1% 14.3% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
1 9.1% 14.3% exp
@@ -34,7 +34,7 @@
2 100.0% LazyCompile: exp native math.js:41
2 100.0% Script: exp.js
- 1 9.1% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
+ 1 9.1% v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 100.0% Script: exp.js
1 9.1% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
diff --git a/test/mjsunit/tools/tickprocessor-test.separate-ic b/test/mjsunit/tools/tickprocessor-test.separate-ic
index 3a2041b..2d49f73 100644
--- a/test/mjsunit/tools/tickprocessor-test.separate-ic
+++ b/test/mjsunit/tools/tickprocessor-test.separate-ic
@@ -18,7 +18,7 @@
[C++]:
ticks total nonlib name
2 15.4% 22.2% v8::internal::Runtime_Math_exp(v8::internal::Arguments)
- 1 7.7% 11.1% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
+ 1 7.7% 11.1% v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 7.7% 11.1% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
1 7.7% 11.1% exp
@@ -40,7 +40,7 @@
2 100.0% LazyCompile: exp native math.js:41
2 100.0% Script: exp.js
- 1 7.7% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
+ 1 7.7% v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 100.0% Script: exp.js
1 7.7% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
diff --git a/test/mjsunit/tools/tickprocessor.js b/test/mjsunit/tools/tickprocessor.js
index 626929d..78a7c43 100644
--- a/test/mjsunit/tools/tickprocessor.js
+++ b/test/mjsunit/tools/tickprocessor.js
@@ -311,7 +311,7 @@
name, startAddr, endAddr, symbolAdder) {
var symbols = {
'shell':
- [['v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)', 0x080f8800, 0x080f8d90],
+ [['v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)', 0x080f8800, 0x080f8d90],
['v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)', 0x080f8210, 0x080f8800],
['v8::internal::Runtime_Math_exp(v8::internal::Arguments)', 0x08123b20, 0x08123b80]],
'/lib32/libm-2.7.so':
diff --git a/test/webkit/fast/js/Object-defineProperty-expected.txt b/test/webkit/fast/js/Object-defineProperty-expected.txt
index 7a303f2..118f9dd 100644
--- a/test/webkit/fast/js/Object-defineProperty-expected.txt
+++ b/test/webkit/fast/js/Object-defineProperty-expected.txt
@@ -142,8 +142,8 @@
PASS Object.getOwnPropertyDescriptor(Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return false; }, configurable: true}), 'foo', {value:false}), 'foo').writable is false
PASS Object.getOwnPropertyDescriptor(Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return false; }, configurable: true}), 'foo', {value:false, writable: false}), 'foo').writable is false
PASS Object.getOwnPropertyDescriptor(Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return false; }, configurable: true}), 'foo', {value:false, writable: true}), 'foo').writable is true
-FAIL var a = Object.defineProperty([], 'length', {writable: false}); a[0] = 42; 0 in a; should be false. Was true.
-FAIL 'use strict'; var a = Object.defineProperty([], 'length', {writable: false}); a[0] = 42; 0 in a; should throw an exception. Was true.
+PASS var a = Object.defineProperty([], 'length', {writable: false}); a[0] = 42; 0 in a; is false
+PASS 'use strict'; var a = Object.defineProperty([], 'length', {writable: false}); a[0] = 42; 0 in a; threw exception TypeError: Cannot assign to read only property 'length' of [object Array].
PASS var a = Object.defineProperty([42], '0', {writable: false}); a[0] = false; a[0]; is 42
PASS 'use strict'; var a = Object.defineProperty([42], '0', {writable: false}); a[0] = false; a[0]; threw exception TypeError: Cannot assign to read only property '0' of [object Array].
PASS var a = Object.defineProperty([], '0', {set: undefined}); a[0] = 42; a[0]; is undefined.
diff --git a/tools/generate-runtime-tests.py b/tools/generate-runtime-tests.py
index 96d4b35..d91986b 100755
--- a/tools/generate-runtime-tests.py
+++ b/tools/generate-runtime-tests.py
@@ -51,7 +51,7 @@
EXPECTED_FUZZABLE_COUNT = 326
EXPECTED_CCTEST_COUNT = 6
EXPECTED_UNKNOWN_COUNT = 5
-EXPECTED_BUILTINS_COUNT = 824
+EXPECTED_BUILTINS_COUNT = 781
# Don't call these at all.
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 1383a60..37b8650 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -46,16 +46,13 @@
# The dependency on v8_base should come from a transitive
# dependency however the Android toolchain requires libv8_base.a
# to appear before libv8_snapshot.a so it's listed explicitly.
- 'dependencies': ['v8_base.<(v8_target_arch)', 'v8_snapshot'],
+ 'dependencies': ['v8_base', 'v8_snapshot'],
},
{
# The dependency on v8_base should come from a transitive
# dependency however the Android toolchain requires libv8_base.a
# to appear before libv8_snapshot.a so it's listed explicitly.
- 'dependencies': [
- 'v8_base.<(v8_target_arch)',
- 'v8_nosnapshot.<(v8_target_arch)',
- ],
+ 'dependencies': ['v8_base', 'v8_nosnapshot'],
}],
['component=="shared_library"', {
'type': '<(component)',
@@ -112,14 +109,14 @@
['want_separate_host_toolset==1', {
'toolsets': ['host', 'target'],
'dependencies': [
- 'mksnapshot.<(v8_target_arch)#host',
+ 'mksnapshot#host',
'js2c#host',
'generate_trig_table#host',
],
}, {
'toolsets': ['target'],
'dependencies': [
- 'mksnapshot.<(v8_target_arch)',
+ 'mksnapshot',
'js2c',
'generate_trig_table',
],
@@ -138,7 +135,7 @@
}],
],
'dependencies': [
- 'v8_base.<(v8_target_arch)',
+ 'v8_base',
],
'include_dirs+': [
'../../src',
@@ -153,7 +150,7 @@
{
'action_name': 'run_mksnapshot',
'inputs': [
- '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot.<(v8_target_arch)<(EXECUTABLE_SUFFIX)',
+ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot<(EXECUTABLE_SUFFIX)',
],
'outputs': [
'<(INTERMEDIATE_DIR)/snapshot.cc',
@@ -178,10 +175,10 @@
],
},
{
- 'target_name': 'v8_nosnapshot.<(v8_target_arch)',
+ 'target_name': 'v8_nosnapshot',
'type': 'static_library',
'dependencies': [
- 'v8_base.<(v8_target_arch)',
+ 'v8_base',
],
'include_dirs+': [
'../../src',
@@ -235,7 +232,7 @@
]
},
{
- 'target_name': 'v8_base.<(v8_target_arch)',
+ 'target_name': 'v8_base',
'type': 'static_library',
'dependencies': [
'v8_libbase.<(v8_target_arch)',
@@ -1176,12 +1173,9 @@
]
},
{
- 'target_name': 'mksnapshot.<(v8_target_arch)',
+ 'target_name': 'mksnapshot',
'type': 'executable',
- 'dependencies': [
- 'v8_base.<(v8_target_arch)',
- 'v8_nosnapshot.<(v8_target_arch)',
- ],
+ 'dependencies': ['v8_base', 'v8_nosnapshot'],
'include_dirs+': [
'../../src',
],