Merge from Chromium at DEPS revision 265802
This commit was generated by merge_to_master.py.
Change-Id: I9415cd7635aaaad246910bf64b52803586457dcd
diff --git a/ChangeLog b/ChangeLog
index 7cc0931..ce43b07 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,60 @@
+2014-04-23: Version 3.26.22
+
+ Disable field type tracking by default (Chromium issue 365172).
+
+ Performance and stability improvements on all platforms.
+
+
+2014-04-23: Version 3.26.21
+
+ Context-allocate all parameters in generators (issue 3280).
+
+ Simplify v8/Isolate teardown (Chromium issue 359977).
+
+ Performance and stability improvements on all platforms.
+
+
+2014-04-21: Version 3.26.20
+
+ ES6: Add support for Map/Set forEach (Chromium issues 1793, 2323).
+
+ Performance and stability improvements on all platforms.
+
+
+2014-04-18: Version 3.26.19
+
+ ES6: Add support for Map/Set forEach (Chromium issues 1793, 2323).
+
+ Performance and stability improvements on all platforms.
+
+
+2014-04-17: Version 3.26.18
+
+ Removed Isolate::EnterDefaultIsolate (Chromium issue 359977).
+
+ Performance and stability improvements on all platforms.
+
+
+2014-04-16: Version 3.26.17
+
+ Clear invalid field maps in PropertyAccessInfo (Chromium issue 363956).
+
+ ES6: Add support for Map/Set forEach (Chromium issues 1793, 2323).
+
+ Performance and stability improvements on all platforms.
+
+
+2014-04-16: Version 3.26.16
+
+ Removed EnterIsolateIfNeeded and a soon-to-be-useless assertion
+ (Chromium issue 359977).
+
+ Removed GetDefaultIsolate{Debugger,ForLocking,StackGuard} (Chromium
+ issue 359977).
+
+ Performance and stability improvements on all platforms.
+
+
2014-04-15: Version 3.26.15
Fix result of LCodeGen::DoWrapReceiver for strict functions and builtins
diff --git a/Makefile b/Makefile
index 0252c57..efd43b9 100644
--- a/Makefile
+++ b/Makefile
@@ -232,7 +232,7 @@
# Architectures and modes to be compiled. Consider these to be internal
# variables, don't override them (use the targets instead).
-ARCHES = ia32 x64 arm arm64 mipsel
+ARCHES = ia32 x64 arm arm64 mips mipsel
DEFAULT_ARCHES = ia32 x64 arm
MODES = release debug optdebug
DEFAULT_MODES = release debug
@@ -281,10 +281,6 @@
$(MAKE) -C "$(OUTDIR)" BUILDTYPE=$(BUILDTYPE) \
builddir="$(abspath $(OUTDIR))/$(BUILDTYPE)"
-mips mips.release mips.debug:
- @echo "V8 does not support big-endian MIPS builds at the moment," \
- "please use little-endian builds (mipsel)."
-
# Compile targets. MODES and ARCHES are convenience targets.
.SECONDEXPANSION:
$(MODES): $(addsuffix .$$@,$(DEFAULT_ARCHES))
diff --git a/Makefile.nacl b/Makefile.nacl
index fc3eb28..1d34a3b 100644
--- a/Makefile.nacl
+++ b/Makefile.nacl
@@ -77,6 +77,9 @@
# ICU doesn't support NaCl.
GYPENV += v8_enable_i18n_support=0
+# Disable strict aliasing - v8 code often relies on undefined behavior of C++.
+GYPENV += v8_no_strict_aliasing=1
+
NACL_MAKEFILES = $(addprefix $(OUTDIR)/Makefile.,$(NACL_BUILDS))
.SECONDEXPANSION:
# For some reason the $$(basename $$@) expansion didn't work here...
diff --git a/build/standalone.gypi b/build/standalone.gypi
index 279d5ae..befa738 100644
--- a/build/standalone.gypi
+++ b/build/standalone.gypi
@@ -55,8 +55,8 @@
'<!(uname -m | sed -e "s/i.86/ia32/;\
s/x86_64/x64/;\
s/amd64/x64/;\
- s/aarch64/arm64/;\
s/arm.*/arm/;\
+ s/aarch64/arm64/;\
s/mips.*/mipsel/")',
}, {
# OS!="linux" and OS!="freebsd" and OS!="openbsd" and
diff --git a/build/toolchain.gypi b/build/toolchain.gypi
index 154ee99..a9958ce 100644
--- a/build/toolchain.gypi
+++ b/build/toolchain.gypi
@@ -278,6 +278,57 @@
'V8_TARGET_ARCH_IA32',
],
}], # v8_target_arch=="ia32"
+ ['v8_target_arch=="mips"', {
+ 'defines': [
+ 'V8_TARGET_ARCH_MIPS',
+ ],
+ 'variables': {
+ 'mipscompiler': '<!($(echo <(CXX)) -v 2>&1 | grep -q "^Target: mips" && echo "yes" || echo "no")',
+ },
+ 'conditions': [
+ ['mipscompiler=="yes"', {
+ 'target_conditions': [
+ ['_toolset=="target"', {
+ 'cflags': ['-EB'],
+ 'ldflags': ['-EB'],
+ 'conditions': [
+ [ 'v8_use_mips_abi_hardfloat=="true"', {
+ 'cflags': ['-mhard-float'],
+ 'ldflags': ['-mhard-float'],
+ }, {
+ 'cflags': ['-msoft-float'],
+ 'ldflags': ['-msoft-float'],
+ }],
+ ['mips_arch_variant=="mips32r2"', {
+ 'cflags': ['-mips32r2', '-Wa,-mips32r2'],
+ }],
+ ['mips_arch_variant=="mips32r1"', {
+ 'cflags': ['-mips32', '-Wa,-mips32'],
+ }],
+ ],
+ }],
+ ],
+ }],
+ [ 'v8_can_use_fpu_instructions=="true"', {
+ 'defines': [
+ 'CAN_USE_FPU_INSTRUCTIONS',
+ ],
+ }],
+ [ 'v8_use_mips_abi_hardfloat=="true"', {
+ 'defines': [
+ '__mips_hard_float=1',
+ 'CAN_USE_FPU_INSTRUCTIONS',
+ ],
+ }, {
+ 'defines': [
+ '__mips_soft_float=1'
+ ],
+ }],
+ ['mips_arch_variant=="mips32r2"', {
+ 'defines': ['_MIPS_ARCH_MIPS32R2',],
+ }],
+ ],
+ }], # v8_target_arch=="mips"
['v8_target_arch=="mipsel"', {
'defines': [
'V8_TARGET_ARCH_MIPS',
@@ -380,7 +431,7 @@
['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
or OS=="netbsd" or OS=="mac" or OS=="android" or OS=="qnx") and \
(v8_target_arch=="arm" or v8_target_arch=="ia32" or \
- v8_target_arch=="mipsel")', {
+ v8_target_arch=="mips" or v8_target_arch=="mipsel")', {
# Check whether the host compiler and target compiler support the
# '-m32' option and set it if so.
'target_conditions': [
diff --git a/include/v8-debug.h b/include/v8-debug.h
index 0199cd2..49916fe 100644
--- a/include/v8-debug.h
+++ b/include/v8-debug.h
@@ -190,32 +190,28 @@
Handle<Value> data = Handle<Value>());
// Schedule a debugger break to happen when JavaScript code is run
- // in the given isolate. If no isolate is provided the default
- // isolate is used.
- static void DebugBreak(Isolate* isolate = NULL);
+ // in the given isolate.
+ static void DebugBreak(Isolate* isolate);
// Remove scheduled debugger break in given isolate if it has not
- // happened yet. If no isolate is provided the default isolate is
- // used.
- static void CancelDebugBreak(Isolate* isolate = NULL);
+ // happened yet.
+ static void CancelDebugBreak(Isolate* isolate);
// Break execution of JavaScript in the given isolate (this method
// can be invoked from a non-VM thread) for further client command
// execution on a VM thread. Client data is then passed in
// EventDetails to EventCallback2 at the moment when the VM actually
- // stops. If no isolate is provided the default isolate is used.
- static void DebugBreakForCommand(ClientData* data = NULL,
- Isolate* isolate = NULL);
+ // stops.
+ static void DebugBreakForCommand(Isolate* isolate, ClientData* data);
+
+ // TODO(svenpanne) Remove this when Chrome is updated.
+ static void DebugBreakForCommand(ClientData* data, Isolate* isolate) {
+ DebugBreakForCommand(isolate, data);
+ }
// Message based interface. The message protocol is JSON.
static void SetMessageHandler2(MessageHandler2 handler);
- // If no isolate is provided the default isolate is
- // used.
- // TODO(dcarney): remove
- static void SendCommand(const uint16_t* command, int length,
- ClientData* client_data = NULL,
- Isolate* isolate = NULL);
static void SendCommand(Isolate* isolate,
const uint16_t* command, int length,
ClientData* client_data = NULL);
@@ -331,7 +327,12 @@
* (default Isolate if not provided). V8 will abort if LiveEdit is
* unexpectedly used. LiveEdit is enabled by default.
*/
- static void SetLiveEditEnabled(bool enable, Isolate* isolate = NULL);
+ static void SetLiveEditEnabled(Isolate* isolate, bool enable);
+
+ // TODO(svenpanne) Remove this when Chrome is updated.
+ static void SetLiveEditEnabled(bool enable, Isolate* isolate) {
+ SetLiveEditEnabled(isolate, enable);
+ }
};
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index f5b760a..026715f 100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -118,14 +118,15 @@
const CpuProfileNode* GetSample(int index) const;
/**
- * Returns time when the profile recording started (in microseconds
- * since the Epoch).
+ * Returns time when the profile recording was started (in microseconds)
+ * since some unspecified starting point.
*/
int64_t GetStartTime() const;
/**
- * Returns time when the profile recording was stopped (in microseconds
- * since the Epoch).
+ * Returns time when the profile recording was stopped (in microseconds)
+ * since some unspecified starting point. The point is however equal to the
+ * starting point used by GetStartTime.
*/
int64_t GetEndTime() const;
diff --git a/include/v8.h b/include/v8.h
index fe02081..1289730 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -3894,8 +3894,8 @@
uint64_t virtual_memory_limit,
uint32_t number_of_processors);
- int max_young_space_size() const { return max_young_space_size_; }
- void set_max_young_space_size(int value) { max_young_space_size_ = value; }
+ int max_new_space_size() const { return max_new_space_size_; }
+ void set_max_new_space_size(int value) { max_new_space_size_ = value; }
int max_old_space_size() const { return max_old_space_size_; }
void set_max_old_space_size(int value) { max_old_space_size_ = value; }
int max_executable_size() const { return max_executable_size_; }
@@ -3914,7 +3914,7 @@
}
private:
- int max_young_space_size_;
+ int max_new_space_size_;
int max_old_space_size_;
int max_executable_size_;
uint32_t* stack_limit_;
@@ -4840,15 +4840,14 @@
/**
* Forcefully terminate the current thread of JavaScript execution
- * in the given isolate. If no isolate is provided, the default
- * isolate is used.
+ * in the given isolate.
*
* This method can be used by any thread even if that thread has not
* acquired the V8 lock with a Locker object.
*
* \param isolate The isolate in which to terminate the current JS execution.
*/
- static void TerminateExecution(Isolate* isolate = NULL);
+ static void TerminateExecution(Isolate* isolate);
/**
* Is V8 terminating JavaScript execution.
@@ -5534,7 +5533,7 @@
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
static const int kContextHeaderSize = 2 * kApiPointerSize;
- static const int kContextEmbedderDataIndex = 65;
+ static const int kContextEmbedderDataIndex = 74;
static const int kFullStringRepresentationMask = 0x07;
static const int kStringEncodingMask = 0x4;
static const int kExternalTwoByteRepresentationTag = 0x02;
@@ -5546,7 +5545,7 @@
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
- static const int kEmptyStringRootIndex = 160;
+ static const int kEmptyStringRootIndex = 162;
static const int kNodeClassIdOffset = 1 * kApiPointerSize;
static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
diff --git a/src/accessors.cc b/src/accessors.cc
index 3030e5d..7a9d725 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -37,11 +37,32 @@
#include "isolate.h"
#include "list-inl.h"
#include "property-details.h"
+#include "api.h"
namespace v8 {
namespace internal {
+static Handle<AccessorInfo> MakeAccessor(Isolate* isolate,
+ Handle<String> name,
+ AccessorGetterCallback getter,
+ AccessorSetterCallback setter,
+ PropertyAttributes attributes) {
+ Factory* factory = isolate->factory();
+ Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
+ info->set_property_attributes(attributes);
+ info->set_all_can_read(true);
+ info->set_all_can_write(true);
+ info->set_prohibits_overwriting(false);
+ info->set_name(*name);
+ Handle<Object> get = v8::FromCData(isolate, getter);
+ Handle<Object> set = v8::FromCData(isolate, setter);
+ info->set_getter(*get);
+ info->set_setter(*set);
+ return info;
+}
+
+
template <class C>
static C* FindInstanceOf(Isolate* isolate, Object* obj) {
for (Object* cur = obj; !cur->IsNull(); cur = cur->GetPrototype(isolate)) {
@@ -105,7 +126,7 @@
}
if (!type->IsClass()) return false;
- Handle<Map> map = type->AsClass();
+ Handle<Map> map = type->AsClass()->Map();
switch (map->instance_type()) {
case JS_ARRAY_TYPE:
@@ -233,122 +254,223 @@
// Accessors::StringLength
//
-
-MaybeObject* Accessors::StringGetLength(Isolate* isolate,
- Object* object,
- void*) {
- Object* value = object;
- if (object->IsJSValue()) value = JSValue::cast(object)->value();
- if (value->IsString()) return Smi::FromInt(String::cast(value)->length());
- // If object is not a string we return 0 to be compatible with WebKit.
- // Note: Firefox returns the length of ToString(object).
- return Smi::FromInt(0);
+void Accessors::StringLengthGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ DisallowHeapAllocation no_allocation;
+ HandleScope scope(isolate);
+ Object* value = *Utils::OpenHandle(*info.This());
+ Object* result;
+ if (value->IsJSValue()) value = JSValue::cast(value)->value();
+ if (value->IsString()) {
+ result = Smi::FromInt(String::cast(value)->length());
+ } else {
+ // If object is not a string we return 0 to be compatible with WebKit.
+ // Note: Firefox returns the length of ToString(object).
+ result = Smi::FromInt(0);
+ }
+ info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
}
-const AccessorDescriptor Accessors::StringLength = {
- StringGetLength,
- IllegalSetter,
- 0
-};
-
-
-//
-// Accessors::ScriptSource
-//
-
-
-MaybeObject* Accessors::ScriptGetSource(Isolate* isolate,
- Object* object,
- void*) {
- Object* script = JSValue::cast(object)->value();
- return Script::cast(script)->source();
+void Accessors::StringLengthSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
}
-const AccessorDescriptor Accessors::ScriptSource = {
- ScriptGetSource,
- IllegalSetter,
- 0
-};
-
-
-//
-// Accessors::ScriptName
-//
-
-
-MaybeObject* Accessors::ScriptGetName(Isolate* isolate,
- Object* object,
- void*) {
- Object* script = JSValue::cast(object)->value();
- return Script::cast(script)->name();
+Handle<AccessorInfo> Accessors::StringLengthInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ return MakeAccessor(isolate,
+ isolate->factory()->length_string(),
+ &StringLengthGetter,
+ &StringLengthSetter,
+ attributes);
}
-const AccessorDescriptor Accessors::ScriptName = {
- ScriptGetName,
- IllegalSetter,
- 0
-};
-
-
-//
-// Accessors::ScriptId
-//
-
-
-MaybeObject* Accessors::ScriptGetId(Isolate* isolate, Object* object, void*) {
- Object* script = JSValue::cast(object)->value();
- return Script::cast(script)->id();
-}
-
-
-const AccessorDescriptor Accessors::ScriptId = {
- ScriptGetId,
- IllegalSetter,
- 0
-};
-
-
-//
-// Accessors::ScriptLineOffset
-//
-
-
-MaybeObject* Accessors::ScriptGetLineOffset(Isolate* isolate,
- Object* object,
- void*) {
- Object* script = JSValue::cast(object)->value();
- return Script::cast(script)->line_offset();
-}
-
-
-const AccessorDescriptor Accessors::ScriptLineOffset = {
- ScriptGetLineOffset,
- IllegalSetter,
- 0
-};
-
-
//
// Accessors::ScriptColumnOffset
//
-MaybeObject* Accessors::ScriptGetColumnOffset(Isolate* isolate,
- Object* object,
- void*) {
- Object* script = JSValue::cast(object)->value();
- return Script::cast(script)->column_offset();
+void Accessors::ScriptColumnOffsetGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ DisallowHeapAllocation no_allocation;
+ HandleScope scope(isolate);
+ Object* object = *Utils::OpenHandle(*info.This());
+ Object* res = Script::cast(JSValue::cast(object)->value())->column_offset();
+ info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
}
-const AccessorDescriptor Accessors::ScriptColumnOffset = {
- ScriptGetColumnOffset,
- IllegalSetter,
- 0
-};
+void Accessors::ScriptColumnOffsetSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ Handle<String> name(isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("column_offset")));
+ return MakeAccessor(isolate,
+ name,
+ &ScriptColumnOffsetGetter,
+ &ScriptColumnOffsetSetter,
+ attributes);
+}
+
+
+//
+// Accessors::ScriptId
+//
+
+
+void Accessors::ScriptIdGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ DisallowHeapAllocation no_allocation;
+ HandleScope scope(isolate);
+ Object* object = *Utils::OpenHandle(*info.This());
+ Object* id = Script::cast(JSValue::cast(object)->value())->id();
+ info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate)));
+}
+
+
+void Accessors::ScriptIdSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptIdInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ Handle<String> name(isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("id")));
+ return MakeAccessor(isolate,
+ name,
+ &ScriptIdGetter,
+ &ScriptIdSetter,
+ attributes);
+}
+
+
+//
+// Accessors::ScriptName
+//
+
+
+void Accessors::ScriptNameGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ DisallowHeapAllocation no_allocation;
+ HandleScope scope(isolate);
+ Object* object = *Utils::OpenHandle(*info.This());
+ Object* source = Script::cast(JSValue::cast(object)->value())->name();
+ info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
+}
+
+
+void Accessors::ScriptNameSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptNameInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ return MakeAccessor(isolate,
+ isolate->factory()->name_string(),
+ &ScriptNameGetter,
+ &ScriptNameSetter,
+ attributes);
+}
+
+
+//
+// Accessors::ScriptSource
+//
+
+
+void Accessors::ScriptSourceGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ DisallowHeapAllocation no_allocation;
+ HandleScope scope(isolate);
+ Object* object = *Utils::OpenHandle(*info.This());
+ Object* source = Script::cast(JSValue::cast(object)->value())->source();
+ info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
+}
+
+
+void Accessors::ScriptSourceSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptSourceInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ return MakeAccessor(isolate,
+ isolate->factory()->source_string(),
+ &ScriptSourceGetter,
+ &ScriptSourceSetter,
+ attributes);
+}
+
+
+//
+// Accessors::ScriptLineOffset
+//
+
+
+void Accessors::ScriptLineOffsetGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ DisallowHeapAllocation no_allocation;
+ HandleScope scope(isolate);
+ Object* object = *Utils::OpenHandle(*info.This());
+ Object* res = Script::cast(JSValue::cast(object)->value())->line_offset();
+ info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
+}
+
+
+void Accessors::ScriptLineOffsetSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ Handle<String> name(isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("line_offset")));
+ return MakeAccessor(isolate,
+ name,
+ &ScriptLineOffsetGetter,
+ &ScriptLineOffsetSetter,
+ attributes);
+}
//
@@ -356,19 +478,36 @@
//
-MaybeObject* Accessors::ScriptGetType(Isolate* isolate,
- Object* object,
- void*) {
- Object* script = JSValue::cast(object)->value();
- return Script::cast(script)->type();
+void Accessors::ScriptTypeGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ DisallowHeapAllocation no_allocation;
+ HandleScope scope(isolate);
+ Object* object = *Utils::OpenHandle(*info.This());
+ Object* res = Script::cast(JSValue::cast(object)->value())->type();
+ info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
}
-const AccessorDescriptor Accessors::ScriptType = {
- ScriptGetType,
- IllegalSetter,
- 0
-};
+void Accessors::ScriptTypeSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptTypeInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ Handle<String> name(isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("type")));
+ return MakeAccessor(isolate,
+ name,
+ &ScriptTypeGetter,
+ &ScriptTypeSetter,
+ attributes);
+}
//
@@ -376,19 +515,37 @@
//
-MaybeObject* Accessors::ScriptGetCompilationType(Isolate* isolate,
- Object* object,
- void*) {
- Object* script = JSValue::cast(object)->value();
- return Smi::FromInt(Script::cast(script)->compilation_type());
+void Accessors::ScriptCompilationTypeGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ DisallowHeapAllocation no_allocation;
+ HandleScope scope(isolate);
+ Object* object = *Utils::OpenHandle(*info.This());
+ Object* res = Smi::FromInt(
+ Script::cast(JSValue::cast(object)->value())->compilation_type());
+ info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
}
-const AccessorDescriptor Accessors::ScriptCompilationType = {
- ScriptGetCompilationType,
- IllegalSetter,
- 0
-};
+void Accessors::ScriptCompilationTypeSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ Handle<String> name(isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("compilation_type")));
+ return MakeAccessor(isolate,
+ name,
+ &ScriptCompilationTypeGetter,
+ &ScriptCompilationTypeSetter,
+ attributes);
+}
//
@@ -396,13 +553,15 @@
//
-MaybeObject* Accessors::ScriptGetLineEnds(Isolate* isolate,
- Object* object,
- void*) {
- JSValue* wrapper = JSValue::cast(object);
+void Accessors::ScriptLineEndsGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
HandleScope scope(isolate);
- Handle<Script> script(Script::cast(wrapper->value()), isolate);
- InitScriptLineEnds(script);
+ Handle<Object> object = Utils::OpenHandle(*info.This());
+ Handle<Script> script(
+ Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
+ Script::InitLineEnds(script);
ASSERT(script->line_ends()->IsFixedArray());
Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
// We do not want anyone to modify this array from JS.
@@ -410,15 +569,28 @@
line_ends->map() == isolate->heap()->fixed_cow_array_map());
Handle<JSArray> js_array =
isolate->factory()->NewJSArrayWithElements(line_ends);
- return *js_array;
+ info.GetReturnValue().Set(Utils::ToLocal(js_array));
}
-const AccessorDescriptor Accessors::ScriptLineEnds = {
- ScriptGetLineEnds,
- IllegalSetter,
- 0
-};
+void Accessors::ScriptLineEndsSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptLineEndsInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ Handle<String> name(isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("line_ends")));
+ return MakeAccessor(isolate,
+ name,
+ &ScriptLineEndsGetter,
+ &ScriptLineEndsSetter,
+ attributes);
+}
//
@@ -426,19 +598,36 @@
//
-MaybeObject* Accessors::ScriptGetContextData(Isolate* isolate,
- Object* object,
- void*) {
- Object* script = JSValue::cast(object)->value();
- return Script::cast(script)->context_data();
+void Accessors::ScriptContextDataGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ DisallowHeapAllocation no_allocation;
+ HandleScope scope(isolate);
+ Object* object = *Utils::OpenHandle(*info.This());
+ Object* res = Script::cast(JSValue::cast(object)->value())->context_data();
+ info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
}
-const AccessorDescriptor Accessors::ScriptContextData = {
- ScriptGetContextData,
- IllegalSetter,
- 0
-};
+void Accessors::ScriptContextDataSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ Handle<String> name(isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("context_data")));
+ return MakeAccessor(isolate,
+ name,
+ &ScriptContextDataGetter,
+ &ScriptContextDataSetter,
+ attributes);
+}
//
@@ -446,28 +635,46 @@
//
-MaybeObject* Accessors::ScriptGetEvalFromScript(Isolate* isolate,
- Object* object,
- void*) {
- Object* script = JSValue::cast(object)->value();
- if (!Script::cast(script)->eval_from_shared()->IsUndefined()) {
+void Accessors::ScriptEvalFromScriptGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ HandleScope scope(isolate);
+ Handle<Object> object = Utils::OpenHandle(*info.This());
+ Handle<Script> script(
+ Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
+ Handle<Object> result = isolate->factory()->undefined_value();
+ if (!script->eval_from_shared()->IsUndefined()) {
Handle<SharedFunctionInfo> eval_from_shared(
- SharedFunctionInfo::cast(Script::cast(script)->eval_from_shared()));
-
+ SharedFunctionInfo::cast(script->eval_from_shared()));
if (eval_from_shared->script()->IsScript()) {
Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
- return *GetScriptWrapper(eval_from_script);
+ result = Script::GetWrapper(eval_from_script);
}
}
- return isolate->heap()->undefined_value();
+
+ info.GetReturnValue().Set(Utils::ToLocal(result));
}
-const AccessorDescriptor Accessors::ScriptEvalFromScript = {
- ScriptGetEvalFromScript,
- IllegalSetter,
- 0
-};
+void Accessors::ScriptEvalFromScriptSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ Handle<String> name(isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("eval_from_script")));
+ return MakeAccessor(isolate,
+ name,
+ &ScriptEvalFromScriptGetter,
+ &ScriptEvalFromScriptSetter,
+ attributes);
+}
//
@@ -475,32 +682,45 @@
//
-MaybeObject* Accessors::ScriptGetEvalFromScriptPosition(Isolate* isolate,
- Object* object,
- void*) {
- Script* raw_script = Script::cast(JSValue::cast(object)->value());
+void Accessors::ScriptEvalFromScriptPositionGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
HandleScope scope(isolate);
- Handle<Script> script(raw_script);
-
- // If this is not a script compiled through eval there is no eval position.
- if (script->compilation_type() != Script::COMPILATION_TYPE_EVAL) {
- return script->GetHeap()->undefined_value();
+ Handle<Object> object = Utils::OpenHandle(*info.This());
+ Handle<Script> script(
+ Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
+ Handle<Object> result = isolate->factory()->undefined_value();
+ if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
+ Handle<Code> code(SharedFunctionInfo::cast(
+ script->eval_from_shared())->code());
+ result = Handle<Object>(
+ Smi::FromInt(code->SourcePosition(code->instruction_start() +
+ script->eval_from_instructions_offset()->value())),
+ isolate);
}
-
- // Get the function from where eval was called and find the source position
- // from the instruction offset.
- Handle<Code> code(SharedFunctionInfo::cast(
- script->eval_from_shared())->code());
- return Smi::FromInt(code->SourcePosition(code->instruction_start() +
- script->eval_from_instructions_offset()->value()));
+ info.GetReturnValue().Set(Utils::ToLocal(result));
}
-const AccessorDescriptor Accessors::ScriptEvalFromScriptPosition = {
- ScriptGetEvalFromScriptPosition,
- IllegalSetter,
- 0
-};
+void Accessors::ScriptEvalFromScriptPositionSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ Handle<String> name(isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("eval_from_script_position")));
+ return MakeAccessor(isolate,
+ name,
+ &ScriptEvalFromScriptPositionGetter,
+ &ScriptEvalFromScriptPositionSetter,
+ attributes);
+}
//
@@ -508,102 +728,100 @@
//
-MaybeObject* Accessors::ScriptGetEvalFromFunctionName(Isolate* isolate,
- Object* object,
- void*) {
- Object* script = JSValue::cast(object)->value();
- Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(
- Script::cast(script)->eval_from_shared()));
-
-
+void Accessors::ScriptEvalFromFunctionNameGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+ HandleScope scope(isolate);
+ Handle<Object> object = Utils::OpenHandle(*info.This());
+ Handle<Script> script(
+ Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
+ Handle<Object> result;
+ Handle<SharedFunctionInfo> shared(
+ SharedFunctionInfo::cast(script->eval_from_shared()));
// Find the name of the function calling eval.
if (!shared->name()->IsUndefined()) {
- return shared->name();
+ result = Handle<Object>(shared->name(), isolate);
} else {
- return shared->inferred_name();
+ result = Handle<Object>(shared->inferred_name(), isolate);
}
+ info.GetReturnValue().Set(Utils::ToLocal(result));
}
-const AccessorDescriptor Accessors::ScriptEvalFromFunctionName = {
- ScriptGetEvalFromFunctionName,
- IllegalSetter,
- 0
-};
+void Accessors::ScriptEvalFromFunctionNameSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<void>& info) {
+ UNREACHABLE();
+}
+
+
+Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ Handle<String> name(isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("eval_from_function_name")));
+ return MakeAccessor(isolate,
+ name,
+ &ScriptEvalFromFunctionNameGetter,
+ &ScriptEvalFromFunctionNameSetter,
+ attributes);
+}
//
// Accessors::FunctionPrototype
//
-
-Handle<Object> Accessors::FunctionGetPrototype(Handle<JSFunction> function) {
- CALL_HEAP_FUNCTION(function->GetIsolate(),
- Accessors::FunctionGetPrototype(function->GetIsolate(),
- *function,
- NULL),
- Object);
-}
-
-
-Handle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
- Handle<Object> prototype) {
- ASSERT(function->should_have_prototype());
- CALL_HEAP_FUNCTION(function->GetIsolate(),
- Accessors::FunctionSetPrototype(function->GetIsolate(),
- *function,
- *prototype,
- NULL),
- Object);
-}
-
-
-MaybeObject* Accessors::FunctionGetPrototype(Isolate* isolate,
- Object* object,
- void*) {
- JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, object);
- if (function_raw == NULL) return isolate->heap()->undefined_value();
- while (!function_raw->should_have_prototype()) {
- function_raw = FindInstanceOf<JSFunction>(isolate,
- function_raw->GetPrototype());
- // There has to be one because we hit the getter.
- ASSERT(function_raw != NULL);
+static Handle<Object> GetFunctionPrototype(Isolate* isolate,
+ Handle<Object> receiver) {
+ Handle<JSFunction> function;
+ {
+ DisallowHeapAllocation no_allocation;
+ JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, *receiver);
+ if (function_raw == NULL) return isolate->factory()->undefined_value();
+ while (!function_raw->should_have_prototype()) {
+ function_raw = FindInstanceOf<JSFunction>(isolate,
+ function_raw->GetPrototype());
+ // There has to be one because we hit the getter.
+ ASSERT(function_raw != NULL);
+ }
+ function = Handle<JSFunction>(function_raw, isolate);
}
- if (!function_raw->has_prototype()) {
- HandleScope scope(isolate);
- Handle<JSFunction> function(function_raw);
+ if (!function->has_prototype()) {
Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
JSFunction::SetPrototype(function, proto);
- function_raw = *function;
}
- return function_raw->prototype();
+ return Handle<Object>(function->prototype(), isolate);
}
-MaybeObject* Accessors::FunctionSetPrototype(Isolate* isolate,
- JSObject* object_raw,
- Object* value_raw,
- void*) {
- JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, object_raw);
- if (function_raw == NULL) return isolate->heap()->undefined_value();
+Handle<Object> Accessors::FunctionGetPrototype(Handle<JSFunction> function) {
+ return GetFunctionPrototype(function->GetIsolate(), function);
+}
- HandleScope scope(isolate);
- Handle<JSFunction> function(function_raw, isolate);
- Handle<JSObject> object(object_raw, isolate);
- Handle<Object> value(value_raw, isolate);
+
+
+MaybeHandle<Object> SetFunctionPrototype(Isolate* isolate,
+ Handle<JSObject> receiver,
+ Handle<Object> value) {
+ Handle<JSFunction> function;
+ {
+ DisallowHeapAllocation no_allocation;
+ JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, *receiver);
+ if (function_raw == NULL) return isolate->factory()->undefined_value();
+ function = Handle<JSFunction>(function_raw, isolate);
+ }
+
if (!function->should_have_prototype()) {
// Since we hit this accessor, object will have no prototype property.
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- JSObject::SetLocalPropertyIgnoreAttributes(
- object, isolate->factory()->prototype_string(), value, NONE));
- return *result;
+ return JSObject::SetLocalPropertyIgnoreAttributes(
+ receiver, isolate->factory()->prototype_string(), value, NONE);
}
Handle<Object> old_value;
- bool is_observed = *function == *object && function->map()->is_observed();
+ bool is_observed = *function == *receiver && function->map()->is_observed();
if (is_observed) {
if (function->has_prototype())
old_value = handle(function->prototype(), isolate);
@@ -619,7 +837,39 @@
function, "update", isolate->factory()->prototype_string(), old_value);
}
- return *function;
+ return function;
+}
+
+
+Handle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
+ Handle<Object> prototype) {
+ ASSERT(function->should_have_prototype());
+ Isolate* isolate = function->GetIsolate();
+ Handle<Object> result;
+ SetFunctionPrototype(isolate, function, prototype).ToHandle(&result);
+ return result;
+}
+
+
+MaybeObject* Accessors::FunctionGetPrototype(Isolate* isolate,
+ Object* object,
+ void*) {
+ HandleScope scope(isolate);
+ return *GetFunctionPrototype(isolate, Handle<Object>(object, isolate));
+}
+
+
+MaybeObject* Accessors::FunctionSetPrototype(Isolate* isolate,
+ JSObject* object,
+ Object* value,
+ void*) {
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ SetFunctionPrototype(isolate,
+ Handle<JSObject>(object, isolate),
+ Handle<Object>(value, isolate)));
+ return *result;
}
@@ -651,7 +901,7 @@
if (Compiler::EnsureCompiled(function_handle, KEEP_EXCEPTION)) {
return Smi::FromInt(function_handle->shared()->length());
}
- return Failure::Exception();
+ return isolate->heap()->exception();
}
diff --git a/src/accessors.h b/src/accessors.h
index 83a8472..196bce5 100644
--- a/src/accessors.h
+++ b/src/accessors.h
@@ -42,20 +42,22 @@
V(FunctionName) \
V(FunctionArguments) \
V(FunctionCaller) \
- V(ArrayLength) \
- V(StringLength) \
- V(ScriptSource) \
- V(ScriptName) \
- V(ScriptId) \
- V(ScriptLineOffset) \
+ V(ArrayLength)
+
+#define ACCESSOR_INFO_LIST(V) \
V(ScriptColumnOffset) \
- V(ScriptType) \
V(ScriptCompilationType) \
- V(ScriptLineEnds) \
V(ScriptContextData) \
V(ScriptEvalFromScript) \
V(ScriptEvalFromScriptPosition) \
- V(ScriptEvalFromFunctionName)
+ V(ScriptEvalFromFunctionName) \
+ V(ScriptId) \
+ V(ScriptLineEnds) \
+ V(ScriptLineOffset) \
+ V(ScriptName) \
+ V(ScriptSource) \
+ V(ScriptType) \
+ V(StringLength)
// Accessors contains all predefined proxy accessors.
@@ -67,11 +69,30 @@
ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
#undef ACCESSOR_DESCRIPTOR_DECLARATION
+#define ACCESSOR_INFO_DECLARATION(name) \
+ static void name##Getter( \
+ v8::Local<v8::String> name, \
+ const v8::PropertyCallbackInfo<v8::Value>& info); \
+ static void name##Setter( \
+ v8::Local<v8::String> name, \
+ v8::Local<v8::Value> value, \
+ const v8::PropertyCallbackInfo<void>& info); \
+ static Handle<AccessorInfo> name##Info( \
+ Isolate* isolate, \
+ PropertyAttributes attributes);
+ ACCESSOR_INFO_LIST(ACCESSOR_INFO_DECLARATION)
+#undef ACCESSOR_INFO_DECLARATION
+
enum DescriptorId {
#define ACCESSOR_DESCRIPTOR_DECLARATION(name) \
k##name,
ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
#undef ACCESSOR_DESCRIPTOR_DECLARATION
+#define ACCESSOR_INFO_DECLARATION(name) \
+ k##name##Getter, \
+ k##name##Setter,
+ ACCESSOR_INFO_LIST(ACCESSOR_INFO_DECLARATION)
+#undef ACCESSOR_INFO_DECLARATION
descriptorCount
};
@@ -92,7 +113,6 @@
Handle<String> name,
int* object_offset);
-
private:
// Accessor functions only used through the descriptor.
static MaybeObject* FunctionSetPrototype(Isolate* isolate,
@@ -117,35 +137,6 @@
Object*,
void*);
static MaybeObject* ArrayGetLength(Isolate* isolate, Object* object, void*);
- static MaybeObject* StringGetLength(Isolate* isolate, Object* object, void*);
- static MaybeObject* ScriptGetName(Isolate* isolate, Object* object, void*);
- static MaybeObject* ScriptGetId(Isolate* isolate, Object* object, void*);
- static MaybeObject* ScriptGetSource(Isolate* isolate, Object* object, void*);
- static MaybeObject* ScriptGetLineOffset(Isolate* isolate,
- Object* object,
- void*);
- static MaybeObject* ScriptGetColumnOffset(Isolate* isolate,
- Object* object,
- void*);
- static MaybeObject* ScriptGetType(Isolate* isolate, Object* object, void*);
- static MaybeObject* ScriptGetCompilationType(Isolate* isolate,
- Object* object,
- void*);
- static MaybeObject* ScriptGetLineEnds(Isolate* isolate,
- Object* object,
- void*);
- static MaybeObject* ScriptGetContextData(Isolate* isolate,
- Object* object,
- void*);
- static MaybeObject* ScriptGetEvalFromScript(Isolate* isolate,
- Object* object,
- void*);
- static MaybeObject* ScriptGetEvalFromScriptPosition(Isolate* isolate,
- Object* object,
- void*);
- static MaybeObject* ScriptGetEvalFromFunctionName(Isolate* isolate,
- Object* object,
- void*);
// Helper functions.
static Handle<Object> FlattenNumber(Isolate* isolate, Handle<Object> value);
diff --git a/src/allocation-site-scopes.cc b/src/allocation-site-scopes.cc
index bbfb39b..80dab8b 100644
--- a/src/allocation-site-scopes.cc
+++ b/src/allocation-site-scopes.cc
@@ -62,7 +62,7 @@
void AllocationSiteCreationContext::ExitScope(
Handle<AllocationSite> scope_site,
Handle<JSObject> object) {
- if (!object.is_null() && !object->IsFailure()) {
+ if (!object.is_null()) {
bool top_level = !scope_site.is_null() &&
top().is_identical_to(scope_site);
diff --git a/src/allocation-tracker.cc b/src/allocation-tracker.cc
index a9103a8..a27dfa4 100644
--- a/src/allocation-tracker.cc
+++ b/src/allocation-tracker.cc
@@ -211,11 +211,6 @@
}
-static bool AddressesMatch(void* key1, void* key2) {
- return key1 == key2;
-}
-
-
void AllocationTracker::DeleteFunctionInfo(FunctionInfo** info) {
delete *info;
}
@@ -225,7 +220,7 @@
HeapObjectsMap* ids, StringsStorage* names)
: ids_(ids),
names_(names),
- id_to_function_info_index_(AddressesMatch),
+ id_to_function_info_index_(HashMap::PointersMatch),
info_index_for_other_state_(0) {
FunctionInfo* info = new FunctionInfo();
info->name = "(root)";
@@ -354,8 +349,8 @@
void AllocationTracker::UnresolvedLocation::Resolve() {
if (script_.is_null()) return;
HandleScope scope(script_->GetIsolate());
- info_->line = GetScriptLineNumber(script_, start_position_);
- info_->column = GetScriptColumnNumber(script_, start_position_);
+ info_->line = Script::GetLineNumber(script_, start_position_);
+ info_->column = Script::GetColumnNumber(script_, start_position_);
}
diff --git a/src/api.cc b/src/api.cc
index bdc0c4f..bd62d10 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -244,24 +244,6 @@
}
-// Some initializing API functions are called early and may be
-// called on a thread different from static initializer thread.
-// If Isolate API is used, Isolate::Enter() will initialize TLS so
-// Isolate::Current() works. If it's a legacy case, then the thread
-// may not have TLS initialized yet. However, in initializing APIs it
-// may be too early to call EnsureInitialized() - some pre-init
-// parameters still have to be configured.
-static inline i::Isolate* EnterIsolateIfNeeded() {
- i::Isolate* isolate = i::Isolate::UncheckedCurrent();
- if (isolate != NULL)
- return isolate;
-
- i::Isolate::EnterDefaultIsolate();
- isolate = i::Isolate::Current();
- return isolate;
-}
-
-
StartupDataDecompressor::StartupDataDecompressor()
: raw_data(i::NewArray<char*>(V8::GetCompressedStartupDataCount())) {
for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
@@ -391,14 +373,14 @@
void V8::SetFatalErrorHandler(FatalErrorCallback that) {
- i::Isolate* isolate = EnterIsolateIfNeeded();
+ i::Isolate* isolate = i::Isolate::UncheckedCurrent();
isolate->set_exception_behavior(that);
}
void V8::SetAllowCodeGenerationFromStringsCallback(
AllowCodeGenerationFromStringsCallback callback) {
- i::Isolate* isolate = EnterIsolateIfNeeded();
+ i::Isolate* isolate = i::Isolate::UncheckedCurrent();
isolate->set_allow_code_gen_callback(callback);
}
@@ -460,7 +442,7 @@
ResourceConstraints::ResourceConstraints()
- : max_young_space_size_(0),
+ : max_new_space_size_(0),
max_old_space_size_(0),
max_executable_size_(0),
stack_limit_(NULL),
@@ -470,7 +452,6 @@
void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
uint64_t virtual_memory_limit,
uint32_t number_of_processors) {
- const int lump_of_memory = (i::kPointerSize / 4) * i::MB;
#if V8_OS_ANDROID
// Android has higher physical memory requirements before raising the maximum
// heap size limits since it has no swap space.
@@ -483,24 +464,22 @@
const uint64_t high_limit = 1ul * i::GB;
#endif
- // The young_space_size should be a power of 2 and old_generation_size should
- // be a multiple of Page::kPageSize.
if (physical_memory <= low_limit) {
- set_max_young_space_size(2 * lump_of_memory);
- set_max_old_space_size(128 * lump_of_memory);
- set_max_executable_size(96 * lump_of_memory);
+ set_max_new_space_size(i::Heap::kMaxNewSpaceSizeLowMemoryDevice);
+ set_max_old_space_size(i::Heap::kMaxOldSpaceSizeLowMemoryDevice);
+ set_max_executable_size(i::Heap::kMaxExecutableSizeLowMemoryDevice);
} else if (physical_memory <= medium_limit) {
- set_max_young_space_size(8 * lump_of_memory);
- set_max_old_space_size(256 * lump_of_memory);
- set_max_executable_size(192 * lump_of_memory);
+ set_max_new_space_size(i::Heap::kMaxNewSpaceSizeMediumMemoryDevice);
+ set_max_old_space_size(i::Heap::kMaxOldSpaceSizeMediumMemoryDevice);
+ set_max_executable_size(i::Heap::kMaxExecutableSizeMediumMemoryDevice);
} else if (physical_memory <= high_limit) {
- set_max_young_space_size(16 * lump_of_memory);
- set_max_old_space_size(512 * lump_of_memory);
- set_max_executable_size(256 * lump_of_memory);
+ set_max_new_space_size(i::Heap::kMaxNewSpaceSizeHighMemoryDevice);
+ set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHighMemoryDevice);
+ set_max_executable_size(i::Heap::kMaxExecutableSizeHighMemoryDevice);
} else {
- set_max_young_space_size(16 * lump_of_memory);
- set_max_old_space_size(700 * lump_of_memory);
- set_max_executable_size(256 * lump_of_memory);
+ set_max_new_space_size(i::Heap::kMaxNewSpaceSizeHugeMemoryDevice);
+ set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHugeMemoryDevice);
+ set_max_executable_size(i::Heap::kMaxExecutableSizeHugeMemoryDevice);
}
set_max_available_threads(i::Max(i::Min(number_of_processors, 4u), 1u));
@@ -517,15 +496,15 @@
bool SetResourceConstraints(Isolate* v8_isolate,
ResourceConstraints* constraints) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
- int young_space_size = constraints->max_young_space_size();
+ int new_space_size = constraints->max_new_space_size();
int old_gen_size = constraints->max_old_space_size();
int max_executable_size = constraints->max_executable_size();
int code_range_size = constraints->code_range_size();
- if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0 ||
+ if (new_space_size != 0 || old_gen_size != 0 || max_executable_size != 0 ||
code_range_size != 0) {
// After initialization it's too late to change Heap constraints.
ASSERT(!isolate->IsInitialized());
- bool result = isolate->heap()->ConfigureHeap(young_space_size / 2,
+ bool result = isolate->heap()->ConfigureHeap(new_space_size / 2,
old_gen_size,
max_executable_size,
code_range_size);
@@ -1633,7 +1612,7 @@
LOG_API(isolate, "UnboundScript::GetLineNumber");
if (obj->IsScript()) {
i::Handle<i::Script> script(i::Script::cast(*obj));
- return i::GetScriptLineNumber(script, code_pos);
+ return i::Script::GetLineNumber(script, code_pos);
} else {
return -1;
}
@@ -2001,11 +1980,9 @@
int argc,
i::Handle<i::Object> argv[]) {
i::Isolate* isolate = i::Isolate::Current();
- i::Handle<i::String> fmt_str =
- isolate->factory()->InternalizeUtf8String(name);
i::Handle<i::Object> object_fun =
i::Object::GetProperty(
- isolate->js_builtins_object(), fmt_str).ToHandleChecked();
+ isolate, isolate->js_builtins_object(), name).ToHandleChecked();
i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(object_fun);
return i::Execution::Call(isolate, fun, recv, argc, argv);
}
@@ -2174,7 +2151,8 @@
ENTER_V8(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- i::Handle<i::Object> line = GetProperty(self, "lineNumber").ToHandleChecked();
+ i::Handle<i::Object> line = i::Object::GetProperty(
+ isolate, self, "lineNumber").ToHandleChecked();
if (!line->IsSmi()) {
return Message::kNoLineNumberInfo;
}
@@ -2187,7 +2165,8 @@
ENTER_V8(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- i::Handle<i::Object> column = GetProperty(self, "column").ToHandleChecked();
+ i::Handle<i::Object> column = i::Object::GetProperty(
+ isolate, self, "column").ToHandleChecked();
if (!column->IsSmi()) {
return Message::kNoColumnInfo;
}
@@ -2200,8 +2179,8 @@
ENTER_V8(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- i::Handle<i::Object> scriptId =
- GetProperty(self, "scriptId").ToHandleChecked();
+ i::Handle<i::Object> scriptId = i::Object::GetProperty(
+ isolate, self, "scriptId").ToHandleChecked();
if (!scriptId->IsSmi()) {
return Message::kNoScriptIdInfo;
}
@@ -2214,7 +2193,8 @@
ENTER_V8(isolate);
EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- i::Handle<i::Object> name = GetProperty(self, "scriptName").ToHandleChecked();
+ i::Handle<i::Object> name = i::Object::GetProperty(
+ isolate, self, "scriptName").ToHandleChecked();
if (!name->IsString()) {
return Local<String>();
}
@@ -2227,8 +2207,8 @@
ENTER_V8(isolate);
EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- i::Handle<i::Object> name =
- GetProperty(self, "scriptNameOrSourceURL").ToHandleChecked();
+ i::Handle<i::Object> name = i::Object::GetProperty(
+ isolate, self, "scriptNameOrSourceURL").ToHandleChecked();
if (!name->IsString()) {
return Local<String>();
}
@@ -2241,8 +2221,8 @@
ENTER_V8(isolate);
EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- i::Handle<i::Object> name =
- GetProperty(self, "functionName").ToHandleChecked();
+ i::Handle<i::Object> name = i::Object::GetProperty(
+ isolate, self, "functionName").ToHandleChecked();
if (!name->IsString()) {
return Local<String>();
}
@@ -2255,7 +2235,8 @@
ENTER_V8(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- i::Handle<i::Object> is_eval = GetProperty(self, "isEval").ToHandleChecked();
+ i::Handle<i::Object> is_eval = i::Object::GetProperty(
+ isolate, self, "isEval").ToHandleChecked();
return is_eval->IsTrue();
}
@@ -2265,8 +2246,8 @@
ENTER_V8(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- i::Handle<i::Object> is_constructor =
- GetProperty(self, "isConstructor").ToHandleChecked();
+ i::Handle<i::Object> is_constructor = i::Object::GetProperty(
+ isolate, self, "isConstructor").ToHandleChecked();
return is_constructor->IsTrue();
}
@@ -2274,12 +2255,12 @@
// --- J S O N ---
Local<Value> JSON::Parse(Local<String> json_string) {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Handle<i::String> string = Utils::OpenHandle(*json_string);
+ i::Isolate* isolate = string->GetIsolate();
EnsureInitializedForIsolate(isolate, "v8::JSON::Parse");
ENTER_V8(isolate);
i::HandleScope scope(isolate);
- i::Handle<i::String> source =
- i::String::Flatten(Utils::OpenHandle(*json_string));
+ i::Handle<i::String> source = i::String::Flatten(string);
EXCEPTION_PREAMBLE(isolate);
i::MaybeHandle<i::Object> maybe_result =
source->IsSeqOneByteString() ? i::JsonParser<true>::Parse(source)
@@ -2417,60 +2398,55 @@
bool Value::IsDate() const {
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ if (!obj->IsHeapObject()) return false;
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
return obj->HasSpecificClassOf(isolate->heap()->Date_string());
}
bool Value::IsStringObject() const {
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ if (!obj->IsHeapObject()) return false;
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
return obj->HasSpecificClassOf(isolate->heap()->String_string());
}
bool Value::IsSymbolObject() const {
- // TODO(svenpanne): these and other test functions should be written such
- // that they do not use Isolate::Current().
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ if (!obj->IsHeapObject()) return false;
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
return obj->HasSpecificClassOf(isolate->heap()->Symbol_string());
}
bool Value::IsNumberObject() const {
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ if (!obj->IsHeapObject()) return false;
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
return obj->HasSpecificClassOf(isolate->heap()->Number_string());
}
-static i::Object* LookupBuiltin(i::Isolate* isolate,
- const char* builtin_name) {
- i::Handle<i::String> string =
- isolate->factory()->InternalizeUtf8String(builtin_name);
- return *i::Object::GetProperty(
- isolate->js_builtins_object(), string).ToHandleChecked();
-}
-
-
static bool CheckConstructor(i::Isolate* isolate,
i::Handle<i::JSObject> obj,
const char* class_name) {
- i::Object* constr = obj->map()->constructor();
+ i::Handle<i::Object> constr(obj->map()->constructor(), isolate);
if (!constr->IsJSFunction()) return false;
- i::JSFunction* func = i::JSFunction::cast(constr);
- return func->shared()->native() &&
- constr == LookupBuiltin(isolate, class_name);
+ i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(constr);
+ return func->shared()->native() && constr.is_identical_to(
+ i::Object::GetProperty(isolate,
+ isolate->js_builtins_object(),
+ class_name).ToHandleChecked());
}
bool Value::IsNativeError() const {
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(this);
if (obj->IsJSObject()) {
i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj));
+ i::Isolate* isolate = js_obj->GetIsolate();
return CheckConstructor(isolate, js_obj, "$Error") ||
CheckConstructor(isolate, js_obj, "$EvalError") ||
CheckConstructor(isolate, js_obj, "$RangeError") ||
@@ -2485,8 +2461,9 @@
bool Value::IsBooleanObject() const {
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ if (!obj->IsHeapObject()) return false;
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
return obj->HasSpecificClassOf(isolate->heap()->Boolean_string());
}
@@ -2572,7 +2549,7 @@
if (obj->IsNumber()) {
num = obj;
} else {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
LOG_API(isolate, "ToNumber");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
@@ -2590,7 +2567,7 @@
if (obj->IsSmi()) {
num = obj;
} else {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
LOG_API(isolate, "ToInteger");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
@@ -2738,45 +2715,55 @@
void v8::Date::CheckCast(v8::Value* that) {
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_string()),
+ i::Isolate* isolate = NULL;
+ if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
+ Utils::ApiCheck(isolate != NULL &&
+ obj->HasSpecificClassOf(isolate->heap()->Date_string()),
"v8::Date::Cast()",
"Could not convert to date");
}
void v8::StringObject::CheckCast(v8::Value* that) {
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_string()),
+ i::Isolate* isolate = NULL;
+ if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
+ Utils::ApiCheck(isolate != NULL &&
+ obj->HasSpecificClassOf(isolate->heap()->String_string()),
"v8::StringObject::Cast()",
"Could not convert to StringObject");
}
void v8::SymbolObject::CheckCast(v8::Value* that) {
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
+ i::Isolate* isolate = NULL;
+ if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
+ Utils::ApiCheck(isolate != NULL &&
+ obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
"v8::SymbolObject::Cast()",
"Could not convert to SymbolObject");
}
void v8::NumberObject::CheckCast(v8::Value* that) {
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_string()),
+ i::Isolate* isolate = NULL;
+ if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
+ Utils::ApiCheck(isolate != NULL &&
+ obj->HasSpecificClassOf(isolate->heap()->Number_string()),
"v8::NumberObject::Cast()",
"Could not convert to NumberObject");
}
void v8::BooleanObject::CheckCast(v8::Value* that) {
- i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
+ i::Isolate* isolate = NULL;
+ if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
+ Utils::ApiCheck(isolate != NULL &&
+ obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
"v8::BooleanObject::Cast()",
"Could not convert to BooleanObject");
}
@@ -2801,7 +2788,7 @@
if (obj->IsNumber()) {
num = obj;
} else {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
LOG_API(isolate, "NumberValue");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
@@ -2819,7 +2806,7 @@
if (obj->IsNumber()) {
num = obj;
} else {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
LOG_API(isolate, "IntegerValue");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
@@ -2841,7 +2828,7 @@
if (obj->IsSmi()) {
num = obj;
} else {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
LOG_API(isolate, "ToInt32");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
@@ -2858,7 +2845,7 @@
if (obj->IsSmi()) {
num = obj;
} else {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
LOG_API(isolate, "ToUInt32");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
@@ -2876,7 +2863,7 @@
if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
return Local<Uint32>();
}
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
LOG_API(isolate, "ToArrayIndex");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
@@ -2904,7 +2891,7 @@
if (obj->IsSmi()) {
return i::Smi::cast(*obj)->value();
} else {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
LOG_API(isolate, "Int32Value (slow)");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
@@ -2981,13 +2968,11 @@
bool Value::SameValue(Handle<Value> that) const {
- i::Isolate* isolate = i::Isolate::Current();
if (!Utils::ApiCheck(this != NULL && !that.IsEmpty(),
"v8::Value::SameValue()",
"Reading from empty handle")) {
return false;
}
- LOG_API(isolate, "SameValue");
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::Object> other = Utils::OpenHandle(*that);
return obj->SameValue(*other);
@@ -2999,7 +2984,7 @@
if (obj->IsSmi()) {
return i::Smi::cast(*obj)->value();
} else {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
LOG_API(isolate, "Uint32Value");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
@@ -3182,7 +3167,8 @@
// to propagate outside.
TryCatch try_catch;
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> result = i::JSObject::SetPrototype(self, value_obj);
+ i::MaybeHandle<i::Object> result = i::JSObject::SetPrototype(
+ self, value_obj);
has_pending_exception = result.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, false);
return true;
@@ -3216,8 +3202,8 @@
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::FixedArray> value;
- has_pending_exception =
- !i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS).ToHandle(&value);
+ has_pending_exception = !i::JSReceiver::GetKeys(
+ self, i::JSReceiver::INCLUDE_PROTOS).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
@@ -3238,8 +3224,8 @@
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::FixedArray> value;
- has_pending_exception =
- !i::GetKeysInFixedArrayFor(self, i::LOCAL_ONLY).ToHandle(&value);
+ has_pending_exception = !i::JSReceiver::GetKeys(
+ self, i::JSReceiver::LOCAL_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
@@ -3410,9 +3396,12 @@
name, getter, setter, data, settings, attributes, signature);
if (info.is_null()) return false;
bool fast = Utils::OpenHandle(obj)->HasFastProperties();
- i::Handle<i::Object> result =
- i::JSObject::SetAccessor(Utils::OpenHandle(obj), info);
- if (result.is_null() || result->IsUndefined()) return false;
+ i::Handle<i::Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, result,
+ i::JSObject::SetAccessor(Utils::OpenHandle(obj), info),
+ false);
+ if (result->IsUndefined()) return false;
if (fast) i::JSObject::TransformToFastProperties(Utils::OpenHandle(obj), 0);
return true;
}
@@ -4050,7 +4039,7 @@
i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
if (func->shared()->script()->IsScript()) {
i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
- i::Handle<i::Object> scriptName = GetScriptNameOrSourceURL(script);
+ i::Handle<i::Object> scriptName = i::Script::GetNameOrSourceURL(script);
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(func->GetIsolate());
v8::ScriptOrigin origin(
Utils::ToLocal(scriptName),
@@ -4069,7 +4058,7 @@
i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
if (func->shared()->script()->IsScript()) {
i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
- return i::GetScriptLineNumber(script, func->shared()->start_position());
+ return i::Script::GetLineNumber(script, func->shared()->start_position());
}
return kLineOffsetNotFound;
}
@@ -4079,7 +4068,7 @@
i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
if (func->shared()->script()->IsScript()) {
i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
- return i::GetScriptColumnNumber(script, func->shared()->start_position());
+ return i::Script::GetColumnNumber(script, func->shared()->start_position());
}
return kLineOffsetNotFound;
}
@@ -5337,9 +5326,10 @@
}
-inline i::Handle<i::String> NewString(i::Factory* factory,
- String::NewStringType type,
- i::Vector<const char> string) {
+MUST_USE_RESULT
+inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
+ String::NewStringType type,
+ i::Vector<const char> string) {
if (type ==String::kInternalizedString) {
return factory->InternalizeUtf8String(string);
}
@@ -5347,9 +5337,10 @@
}
-inline i::Handle<i::String> NewString(i::Factory* factory,
- String::NewStringType type,
- i::Vector<const uint8_t> string) {
+MUST_USE_RESULT
+inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
+ String::NewStringType type,
+ i::Vector<const uint8_t> string) {
if (type == String::kInternalizedString) {
return factory->InternalizeOneByteString(string);
}
@@ -5357,9 +5348,10 @@
}
-inline i::Handle<i::String> NewString(i::Factory* factory,
- String::NewStringType type,
- i::Vector<const uint16_t> string) {
+MUST_USE_RESULT
+inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
+ String::NewStringType type,
+ i::Vector<const uint16_t> string) {
if (type == String::kInternalizedString) {
return factory->InternalizeTwoByteString(string);
}
@@ -5382,10 +5374,11 @@
}
ENTER_V8(isolate);
if (length == -1) length = StringLength(data);
- i::Handle<i::String> result = NewString(
- isolate->factory(), type, i::Vector<const Char>(data, length));
// We do not expect this to fail. Change this if it does.
- CHECK(!result.is_null());
+ i::Handle<i::String> result = NewString(
+ isolate->factory(),
+ type,
+ i::Vector<const Char>(data, length)).ToHandleChecked();
if (type == String::kUndetectableString) {
result->MarkAsUndetectable();
}
@@ -5586,10 +5579,10 @@
double v8::NumberObject::ValueOf() const {
- i::Isolate* isolate = i::Isolate::Current();
- LOG_API(isolate, "NumberObject::NumberValue");
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+ i::Isolate* isolate = jsvalue->GetIsolate();
+ LOG_API(isolate, "NumberObject::NumberValue");
return jsvalue->value()->Number();
}
@@ -5610,30 +5603,31 @@
bool v8::BooleanObject::ValueOf() const {
- i::Isolate* isolate = i::Isolate::Current();
- LOG_API(isolate, "BooleanObject::BooleanValue");
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+ i::Isolate* isolate = jsvalue->GetIsolate();
+ LOG_API(isolate, "BooleanObject::BooleanValue");
return jsvalue->value()->IsTrue();
}
Local<v8::Value> v8::StringObject::New(Handle<String> value) {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Handle<i::String> string = Utils::OpenHandle(*value);
+ i::Isolate* isolate = string->GetIsolate();
EnsureInitializedForIsolate(isolate, "v8::StringObject::New()");
LOG_API(isolate, "StringObject::New");
ENTER_V8(isolate);
- i::Handle<i::Object> obj = i::Object::ToObject(
- isolate, Utils::OpenHandle(*value)).ToHandleChecked();
+ i::Handle<i::Object> obj =
+ i::Object::ToObject(isolate, string).ToHandleChecked();
return Utils::ToLocal(obj);
}
Local<v8::String> v8::StringObject::ValueOf() const {
- i::Isolate* isolate = i::Isolate::Current();
- LOG_API(isolate, "StringObject::StringValue");
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+ i::Isolate* isolate = jsvalue->GetIsolate();
+ LOG_API(isolate, "StringObject::StringValue");
return Utils::ToLocal(
i::Handle<i::String>(i::String::cast(jsvalue->value())));
}
@@ -5651,10 +5645,10 @@
Local<v8::Symbol> v8::SymbolObject::ValueOf() const {
- i::Isolate* isolate = i::Isolate::Current();
- LOG_API(isolate, "SymbolObject::SymbolValue");
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+ i::Isolate* isolate = jsvalue->GetIsolate();
+ LOG_API(isolate, "SymbolObject::SymbolValue");
return Utils::ToLocal(
i::Handle<i::Symbol>(i::Symbol::cast(jsvalue->value())));
}
@@ -5679,10 +5673,10 @@
double v8::Date::ValueOf() const {
- i::Isolate* isolate = i::Isolate::Current();
- LOG_API(isolate, "Date::NumberValue");
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
+ i::Isolate* isolate = jsdate->GetIsolate();
+ LOG_API(isolate, "Date::NumberValue");
return jsdate->value()->Number();
}
@@ -6086,7 +6080,7 @@
#define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size) \
Local<Type##Array> Type##Array::New(Handle<ArrayBuffer> array_buffer, \
size_t byte_offset, size_t length) { \
- i::Isolate* isolate = i::Isolate::Current(); \
+ i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate(); \
EnsureInitializedForIsolate(isolate, \
"v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)"); \
LOG_API(isolate, \
@@ -6110,13 +6104,13 @@
Local<DataView> DataView::New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t byte_length) {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
+ i::Isolate* isolate = buffer->GetIsolate();
EnsureInitializedForIsolate(
isolate, "v8::DataView::New(void*, size_t, size_t)");
LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)");
ENTER_V8(isolate);
i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView();
- i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
SetupArrayBufferView(
isolate, obj, buffer, byte_offset, byte_length);
return Utils::ToLocal(obj);
@@ -6296,13 +6290,17 @@
void V8::SetCounterFunction(CounterLookupCallback callback) {
- i::Isolate* isolate = EnterIsolateIfNeeded();
+ i::Isolate* isolate = i::Isolate::UncheckedCurrent();
+ // TODO(svenpanne) The Isolate should really be a parameter.
+ if (isolate == NULL) return;
isolate->stats_table()->SetCounterFunction(callback);
}
void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
- i::Isolate* isolate = EnterIsolateIfNeeded();
+ i::Isolate* isolate = i::Isolate::UncheckedCurrent();
+ // TODO(svenpanne) The Isolate should really be a parameter.
+ if (isolate == NULL) return;
isolate->stats_table()->SetCreateHistogramFunction(callback);
isolate->InitializeLoggingAndCounters();
isolate->counters()->ResetHistograms();
@@ -6310,7 +6308,9 @@
void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
- i::Isolate* isolate = EnterIsolateIfNeeded();
+ i::Isolate* isolate = i::Isolate::UncheckedCurrent();
+ // TODO(svenpanne) The Isolate should really be a parameter.
+ if (isolate == NULL) return;
isolate->stats_table()->
SetAddHistogramSampleFunction(callback);
}
@@ -6522,12 +6522,7 @@
void V8::TerminateExecution(Isolate* isolate) {
- // If no isolate is supplied, use the default isolate.
- if (isolate != NULL) {
- reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->TerminateExecution();
- } else {
- i::Isolate::GetDefaultIsolateStackGuard()->TerminateExecution();
- }
+ reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->TerminateExecution();
}
@@ -6844,34 +6839,19 @@
void Debug::DebugBreak(Isolate* isolate) {
- // If no isolate is supplied, use the default isolate.
- if (isolate != NULL) {
- reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->DebugBreak();
- } else {
- i::Isolate::GetDefaultIsolateStackGuard()->DebugBreak();
- }
+ reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->DebugBreak();
}
void Debug::CancelDebugBreak(Isolate* isolate) {
- // If no isolate is supplied, use the default isolate.
- if (isolate != NULL) {
- i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- internal_isolate->stack_guard()->Continue(i::DEBUGBREAK);
- } else {
- i::Isolate::GetDefaultIsolateStackGuard()->Continue(i::DEBUGBREAK);
- }
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ internal_isolate->stack_guard()->Continue(i::DEBUGBREAK);
}
-void Debug::DebugBreakForCommand(ClientData* data, Isolate* isolate) {
- // If no isolate is supplied, use the default isolate.
- if (isolate != NULL) {
- i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- internal_isolate->debugger()->EnqueueDebugCommand(data);
- } else {
- i::Isolate::GetDefaultIsolateDebugger()->EnqueueDebugCommand(data);
- }
+void Debug::DebugBreakForCommand(Isolate* isolate, ClientData* data) {
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ internal_isolate->debugger()->EnqueueDebugCommand(data);
}
@@ -6893,21 +6873,6 @@
}
-void Debug::SendCommand(const uint16_t* command, int length,
- ClientData* client_data,
- Isolate* isolate) {
- // If no isolate is supplied, use the default isolate.
- if (isolate != NULL) {
- i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- internal_isolate->debugger()->ProcessCommand(
- i::Vector<const uint16_t>(command, length), client_data);
- } else {
- i::Isolate::GetDefaultIsolateDebugger()->ProcessCommand(
- i::Vector<const uint16_t>(command, length), client_data);
- }
-}
-
-
void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
int period) {
i::Isolate* isolate = i::Isolate::Current();
@@ -7004,16 +6969,9 @@
}
-void Debug::SetLiveEditEnabled(bool enable, Isolate* isolate) {
- // If no isolate is supplied, use the default isolate.
- i::Debugger* debugger;
- if (isolate != NULL) {
- i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- debugger = internal_isolate->debugger();
- } else {
- debugger = i::Isolate::GetDefaultIsolateDebugger();
- }
- debugger->set_live_edit_enabled(enable);
+void Debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ internal_isolate->debugger()->set_live_edit_enabled(enable);
}
@@ -7127,13 +7085,13 @@
int64_t CpuProfile::GetStartTime() const {
const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
- return (profile->start_time() - i::Time::UnixEpoch()).InMicroseconds();
+ return (profile->start_time() - i::TimeTicks()).InMicroseconds();
}
int64_t CpuProfile::GetEndTime() const {
const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
- return (profile->end_time() - i::Time::UnixEpoch()).InMicroseconds();
+ return (profile->end_time() - i::TimeTicks()).InMicroseconds();
}
diff --git a/src/arguments.h b/src/arguments.h
index b7137c3..7e13d4b 100644
--- a/src/arguments.h
+++ b/src/arguments.h
@@ -299,10 +299,10 @@
#endif
-#define DECLARE_RUNTIME_FUNCTION(Type, Name) \
-Type Name(int args_length, Object** args_object, Isolate* isolate)
+#define DECLARE_RUNTIME_FUNCTION(Name) \
+Object* Name(int args_length, Object** args_object, Isolate* isolate)
-#define RUNTIME_FUNCTION(Type, Name) \
+#define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name) \
static Type __RT_impl_##Name(Arguments args, Isolate* isolate); \
Type Name(int args_length, Object** args_object, Isolate* isolate) { \
CLOBBER_DOUBLE_REGISTERS(); \
@@ -311,6 +311,11 @@
} \
static Type __RT_impl_##Name(Arguments args, Isolate* isolate)
+
+#define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name)
+#define RUNTIME_FUNCTION_RETURN_PAIR(Name) \
+ RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name)
+
#define RUNTIME_ARGUMENTS(isolate, args) \
args.length(), args.arguments(), isolate
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 516d3dd..d08f155 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -48,6 +48,7 @@
#ifdef DEBUG
bool CpuFeatures::initialized_ = false;
#endif
+bool CpuFeatures::hint_creating_snapshot_ = false;
unsigned CpuFeatures::supported_ = 0;
unsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
unsigned CpuFeatures::cross_compile_ = 0;
@@ -100,10 +101,27 @@
}
+void CpuFeatures::SetHintCreatingSnapshot() {
+ hint_creating_snapshot_ = true;
+}
+
+
+void CpuFeatures::ProbeWithoutIsolate() {
+ Probe(hint_creating_snapshot_);
+}
+
+
void CpuFeatures::Probe() {
+ // The Serializer can only be queried after isolate initialization.
+ Probe(Serializer::enabled());
+}
+
+
+void CpuFeatures::Probe(bool serializer_enabled) {
uint64_t standard_features = static_cast<unsigned>(
OS::CpuFeaturesImpliedByPlatform()) | CpuFeaturesImpliedByCompiler();
- ASSERT(supported_ == 0 || supported_ == standard_features);
+ ASSERT(supported_ == 0 ||
+ (supported_ & standard_features) == standard_features);
#ifdef DEBUG
initialized_ = true;
#endif
@@ -113,7 +131,7 @@
// snapshot.
supported_ |= standard_features;
- if (Serializer::enabled()) {
+ if (serializer_enabled) {
// No probing for features if we might serialize (generate snapshot).
printf(" ");
PrintFeatures();
@@ -1079,11 +1097,6 @@
// encoded.
bool Operand::must_output_reloc_info(const Assembler* assembler) const {
if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
-#ifdef DEBUG
- if (!Serializer::enabled()) {
- Serializer::TooLateToEnableNow();
- }
-#endif // def DEBUG
if (assembler != NULL && assembler->predictable_code_size()) return true;
return Serializer::enabled();
} else if (RelocInfo::IsNone(rmode_)) {
@@ -3267,11 +3280,6 @@
if (!RelocInfo::IsNone(rinfo.rmode())) {
// Don't record external references unless the heap will be serialized.
if (rinfo.rmode() == RelocInfo::EXTERNAL_REFERENCE) {
-#ifdef DEBUG
- if (!Serializer::enabled()) {
- Serializer::TooLateToEnableNow();
- }
-#endif
if (!Serializer::enabled() && !emit_debug_code()) {
return;
}
@@ -3548,14 +3556,15 @@
}
-MaybeObject* Assembler::AllocateConstantPool(Heap* heap) {
- ASSERT(FLAG_enable_ool_constant_pool);
- return constant_pool_builder_.Allocate(heap);
+Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
+ if (!FLAG_enable_ool_constant_pool) {
+ return isolate->factory()->empty_constant_pool_array();
+ }
+ return constant_pool_builder_.New(isolate);
}
void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
- ASSERT(FLAG_enable_ool_constant_pool);
constant_pool_builder_.Populate(this, constant_pool);
}
@@ -3655,12 +3664,14 @@
}
-MaybeObject* ConstantPoolBuilder::Allocate(Heap* heap) {
+Handle<ConstantPoolArray> ConstantPoolBuilder::New(Isolate* isolate) {
if (IsEmpty()) {
- return heap->empty_constant_pool_array();
+ return isolate->factory()->empty_constant_pool_array();
} else {
- return heap->AllocateConstantPoolArray(count_of_64bit_, count_of_code_ptr_,
- count_of_heap_ptr_, count_of_32bit_);
+ return isolate->factory()->NewConstantPoolArray(count_of_64bit_,
+ count_of_code_ptr_,
+ count_of_heap_ptr_,
+ count_of_32bit_);
}
}
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 727b054..f64cc5c 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -58,6 +58,11 @@
// is enabled (snapshots must be portable).
static void Probe();
+ // A special case for printing target and features, which we want to do
+ // before initializing the isolate
+ static void SetHintCreatingSnapshot();
+ static void ProbeWithoutIsolate();
+
// Display target use when compiling.
static void PrintTarget();
@@ -94,6 +99,9 @@
}
private:
+ static void Probe(bool serializer_enabled);
+ static bool hint_creating_snapshot_;
+
static bool Check(CpuFeature f, unsigned set) {
return (set & flag2set(f)) != 0;
}
@@ -714,7 +722,7 @@
void AddEntry(Assembler* assm, const RelocInfo& rinfo);
void Relocate(int pc_delta);
bool IsEmpty();
- MaybeObject* Allocate(Heap* heap);
+ Handle<ConstantPoolArray> New(Isolate* isolate);
void Populate(Assembler* assm, ConstantPoolArray* constant_pool);
inline int count_of_64bit() const { return count_of_64bit_; }
@@ -1498,7 +1506,7 @@
void CheckConstPool(bool force_emit, bool require_jump);
// Allocate a constant pool of the correct size for the generated code.
- MaybeObject* AllocateConstantPool(Heap* heap);
+ Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
// Generate the constant pool for the generated code.
void PopulateConstantPool(ConstantPoolArray* constant_pool);
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index f138146..81d7fcb 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -1284,7 +1284,7 @@
// Out of stack space.
__ ldr(r1, MemOperand(fp, kFunctionOffset));
__ Push(r1, r0);
- __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
// End of stack check.
// Push current limit and index.
@@ -1407,6 +1407,26 @@
}
+static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
+ Label* stack_overflow) {
+ // ----------- S t a t e -------------
+ // -- r0 : actual number of arguments
+ // -- r1 : function (passed through to callee)
+ // -- r2 : expected number of arguments
+ // -----------------------------------
+ // Check the stack for overflow. We are not trying to catch
+ // interruptions (e.g. debug break and preemption) here, so the "real stack
+ // limit" is checked.
+ __ LoadRoot(r5, Heap::kRealStackLimitRootIndex);
+ // Make r5 the space we have left. The stack might already be overflowed
+ // here which will cause r5 to become negative.
+ __ sub(r5, sp, r5);
+ // Check if the arguments will overflow the stack.
+ __ cmp(r5, Operand(r2, LSL, kPointerSizeLog2));
+ __ b(le, stack_overflow); // Signed comparison.
+}
+
+
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
__ SmiTag(r0);
__ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
@@ -1446,6 +1466,8 @@
// -- r2 : expected number of arguments
// -----------------------------------
+ Label stack_overflow;
+ ArgumentAdaptorStackCheck(masm, &stack_overflow);
Label invoke, dont_adapt_arguments;
Label enough, too_few;
@@ -1545,6 +1567,14 @@
// -------------------------------------------
__ bind(&dont_adapt_arguments);
__ Jump(r3);
+
+ __ bind(&stack_overflow);
+ {
+ FrameScope frame(masm, StackFrame::MANUAL);
+ EnterArgumentsAdaptorFrame(masm);
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
+ __ bkpt(0);
+ }
}
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index a3d740b..be876b6 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -1502,39 +1502,37 @@
}
-void CEntryStub::GenerateCore(MacroAssembler* masm,
- Label* throw_normal_exception,
- Label* throw_termination_exception,
- bool do_gc,
- bool always_allocate) {
- // r0: result parameter for PerformGC, if any
- // r4: number of arguments including receiver (C callee-saved)
+void CEntryStub::Generate(MacroAssembler* masm) {
+ // Called from JavaScript; parameters are on stack as if calling JS function.
+ // r0: number of arguments including receiver
+ // r1: pointer to builtin function
+ // fp: frame pointer (restored after C call)
+ // sp: stack pointer (restored as callee's sp after C call)
+ // cp: current context (C callee-saved)
+
+ ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
+ __ mov(r5, Operand(r1));
+
+ // Compute the argv pointer in a callee-saved register.
+ __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2));
+ __ sub(r1, r1, Operand(kPointerSize));
+
+ // Enter the exit frame that transitions from JavaScript to C++.
+ FrameScope scope(masm, StackFrame::MANUAL);
+ __ EnterExitFrame(save_doubles_);
+
+ // Store a copy of argc in callee-saved registers for later.
+ __ mov(r4, Operand(r0));
+
+ // r0, r4: number of arguments including receiver (C callee-saved)
+ // r1: pointer to the first argument (C callee-saved)
// r5: pointer to builtin function (C callee-saved)
- // r6: pointer to the first argument (C callee-saved)
+
+ // Result returned in r0 or r0+r1 by default.
+
Isolate* isolate = masm->isolate();
- if (do_gc) {
- // Passing r0.
- __ PrepareCallCFunction(2, 0, r1);
- __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
- __ CallCFunction(ExternalReference::perform_gc_function(isolate),
- 2, 0);
- }
-
- ExternalReference scope_depth =
- ExternalReference::heap_always_allocate_scope_depth(isolate);
- if (always_allocate) {
- __ mov(r0, Operand(scope_depth));
- __ ldr(r1, MemOperand(r0));
- __ add(r1, r1, Operand(1));
- __ str(r1, MemOperand(r0));
- }
-
- // Call C built-in.
- // r0 = argc, r1 = argv
- __ mov(r0, Operand(r4));
- __ mov(r1, Operand(r6));
-
#if V8_HOST_ARCH_ARM
int frame_alignment = MacroAssembler::ActivationFrameAlignment();
int frame_alignment_mask = frame_alignment - 1;
@@ -1551,6 +1549,8 @@
}
#endif
+ // Call C built-in.
+ // r0 = argc, r1 = argv
__ mov(r2, Operand(ExternalReference::isolate_address(isolate)));
// To let the GC traverse the return address of the exit frames, we need to
@@ -1570,132 +1570,67 @@
__ VFPEnsureFPSCRState(r2);
- if (always_allocate) {
- // It's okay to clobber r2 and r3 here. Don't mess with r0 and r1
- // though (contain the result).
- __ mov(r2, Operand(scope_depth));
- __ ldr(r3, MemOperand(r2));
- __ sub(r3, r3, Operand(1));
- __ str(r3, MemOperand(r2));
+ // Runtime functions should not return 'the hole'. Allowing it to escape may
+ // lead to crashes in the IC code later.
+ if (FLAG_debug_code) {
+ Label okay;
+ __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
+ __ b(ne, &okay);
+ __ stop("The hole escaped");
+ __ bind(&okay);
}
- // check for failure result
- Label failure_returned;
- STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
- // Lower 2 bits of r2 are 0 iff r0 has failure tag.
- __ add(r2, r0, Operand(1));
- __ tst(r2, Operand(kFailureTagMask));
- __ b(eq, &failure_returned);
+ // Check result for exception sentinel.
+ Label exception_returned;
+ __ CompareRoot(r0, Heap::kExceptionRootIndex);
+ __ b(eq, &exception_returned);
+
+ ExternalReference pending_exception_address(
+ Isolate::kPendingExceptionAddress, isolate);
+
+ // Check that there is no pending exception, otherwise we
+ // should have returned the exception sentinel.
+ if (FLAG_debug_code) {
+ Label okay;
+ __ mov(r2, Operand(pending_exception_address));
+ __ ldr(r2, MemOperand(r2));
+ __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
+ // Cannot use check here as it attempts to generate call into runtime.
+ __ b(eq, &okay);
+ __ stop("Unexpected pending exception");
+ __ bind(&okay);
+ }
// Exit C frame and return.
// r0:r1: result
// sp: stack pointer
// fp: frame pointer
- // Callee-saved register r4 still holds argc.
+ // Callee-saved register r4 still holds argc.
__ LeaveExitFrame(save_doubles_, r4, true);
__ mov(pc, lr);
- // check if we should retry or throw exception
- Label retry;
- __ bind(&failure_returned);
- STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
- __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
- __ b(eq, &retry);
+ // Handling of exception.
+ __ bind(&exception_returned);
// Retrieve the pending exception.
- __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
- isolate)));
- __ ldr(r0, MemOperand(ip));
+ __ mov(r2, Operand(pending_exception_address));
+ __ ldr(r0, MemOperand(r2));
// Clear the pending exception.
__ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
- __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
- isolate)));
- __ str(r3, MemOperand(ip));
+ __ str(r3, MemOperand(r2));
// Special handling of termination exceptions which are uncatchable
// by javascript code.
- __ LoadRoot(r3, Heap::kTerminationExceptionRootIndex);
- __ cmp(r0, r3);
- __ b(eq, throw_termination_exception);
+ Label throw_termination_exception;
+ __ CompareRoot(r0, Heap::kTerminationExceptionRootIndex);
+ __ b(eq, &throw_termination_exception);
// Handle normal exception.
- __ jmp(throw_normal_exception);
-
- __ bind(&retry); // pass last failure (r0) as parameter (r0) when retrying
-}
-
-
-void CEntryStub::Generate(MacroAssembler* masm) {
- // Called from JavaScript; parameters are on stack as if calling JS function
- // r0: number of arguments including receiver
- // r1: pointer to builtin function
- // fp: frame pointer (restored after C call)
- // sp: stack pointer (restored as callee's sp after C call)
- // cp: current context (C callee-saved)
-
- ProfileEntryHookStub::MaybeCallEntryHook(masm);
-
- // Result returned in r0 or r0+r1 by default.
-
- // NOTE: Invocations of builtins may return failure objects
- // instead of a proper result. The builtin entry handles
- // this by performing a garbage collection and retrying the
- // builtin once.
-
- // Compute the argv pointer in a callee-saved register.
- __ add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
- __ sub(r6, r6, Operand(kPointerSize));
-
- // Enter the exit frame that transitions from JavaScript to C++.
- FrameScope scope(masm, StackFrame::MANUAL);
- __ EnterExitFrame(save_doubles_);
-
- // Set up argc and the builtin function in callee-saved registers.
- __ mov(r4, Operand(r0));
- __ mov(r5, Operand(r1));
-
- // r4: number of arguments (C callee-saved)
- // r5: pointer to builtin function (C callee-saved)
- // r6: pointer to first argument (C callee-saved)
-
- Label throw_normal_exception;
- Label throw_termination_exception;
-
- // Call into the runtime system.
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- false,
- false);
-
- // Do space-specific GC and retry runtime call.
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- true,
- false);
-
- // Do full GC and retry runtime call one final time.
- Failure* failure = Failure::InternalError();
- __ mov(r0, Operand(reinterpret_cast<int32_t>(failure)));
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- true,
- true);
-
- { FrameScope scope(masm, StackFrame::MANUAL);
- __ PrepareCallCFunction(0, r0);
- __ CallCFunction(
- ExternalReference::out_of_memory_function(masm->isolate()), 0, 0);
- }
+ __ Throw(r0);
__ bind(&throw_termination_exception);
__ ThrowUncatchable(r0);
-
- __ bind(&throw_normal_exception);
- __ Throw(r0);
}
@@ -1791,7 +1726,7 @@
isolate)));
}
__ str(r0, MemOperand(ip));
- __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
+ __ LoadRoot(r0, Heap::kExceptionRootIndex);
__ b(&exit);
// Invoke: Link this frame into the handler chain. There's only one
@@ -3842,211 +3777,6 @@
}
-void ArrayPushStub::Generate(MacroAssembler* masm) {
- Register receiver = r0;
- Register scratch = r1;
-
- int argc = arguments_count();
-
- if (argc == 0) {
- // Nothing to do, just return the length.
- __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ Drop(argc + 1);
- __ Ret();
- return;
- }
-
- Isolate* isolate = masm->isolate();
-
- if (argc != 1) {
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- Label call_builtin, attempt_to_grow_elements, with_write_barrier;
-
- Register elements = r6;
- Register end_elements = r5;
- // Get the elements array of the object.
- __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
-
- if (IsFastSmiOrObjectElementsKind(elements_kind())) {
- // Check that the elements are in fast mode and writable.
- __ CheckMap(elements,
- scratch,
- Heap::kFixedArrayMapRootIndex,
- &call_builtin,
- DONT_DO_SMI_CHECK);
- }
-
- // Get the array's length into scratch and calculate new length.
- __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ add(scratch, scratch, Operand(Smi::FromInt(argc)));
-
- // Get the elements' length.
- __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
-
- // Check if we could survive without allocation.
- __ cmp(scratch, r4);
-
- const int kEndElementsOffset =
- FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
-
- if (IsFastSmiOrObjectElementsKind(elements_kind())) {
- __ b(gt, &attempt_to_grow_elements);
-
- // Check if value is a smi.
- __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
- __ JumpIfNotSmi(r4, &with_write_barrier);
-
- // Store the value.
- // We may need a register containing the address end_elements below, so
- // write back the value in end_elements.
- __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
- __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
- } else {
- // Check if we could survive without allocation.
- __ cmp(scratch, r4);
- __ b(gt, &call_builtin);
-
- __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
- __ StoreNumberToDoubleElements(r4, scratch, elements, r5, d0,
- &call_builtin, argc * kDoubleSize);
- }
-
- // Save new length.
- __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ Drop(argc + 1);
- __ mov(r0, scratch);
- __ Ret();
-
- if (IsFastDoubleElementsKind(elements_kind())) {
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- __ bind(&with_write_barrier);
-
- if (IsFastSmiElementsKind(elements_kind())) {
- if (FLAG_trace_elements_transitions) __ jmp(&call_builtin);
-
- __ ldr(r9, FieldMemOperand(r4, HeapObject::kMapOffset));
- __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
- __ cmp(r9, ip);
- __ b(eq, &call_builtin);
-
- ElementsKind target_kind = IsHoleyElementsKind(elements_kind())
- ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
- __ ldr(r3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
- __ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset));
- __ ldr(r3, ContextOperand(r3, Context::JS_ARRAY_MAPS_INDEX));
- const int header_size = FixedArrayBase::kHeaderSize;
- // Verify that the object can be transitioned in place.
- const int origin_offset = header_size + elements_kind() * kPointerSize;
- __ ldr(r2, FieldMemOperand(receiver, origin_offset));
- __ ldr(ip, FieldMemOperand(r3, HeapObject::kMapOffset));
- __ cmp(r2, ip);
- __ b(ne, &call_builtin);
-
- const int target_offset = header_size + target_kind * kPointerSize;
- __ ldr(r3, FieldMemOperand(r3, target_offset));
- __ mov(r2, receiver);
- ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
- masm, DONT_TRACK_ALLOCATION_SITE, NULL);
- }
-
- // Save new length.
- __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
-
- // Store the value.
- // We may need a register containing the address end_elements below, so write
- // back the value in end_elements.
- __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
- __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
-
- __ RecordWrite(elements,
- end_elements,
- r4,
- kLRHasNotBeenSaved,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- __ Drop(argc + 1);
- __ mov(r0, scratch);
- __ Ret();
-
- __ bind(&attempt_to_grow_elements);
- // scratch: array's length + 1.
-
- if (!FLAG_inline_new) {
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- __ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize));
- // Growing elements that are SMI-only requires special handling in case the
- // new element is non-Smi. For now, delegate to the builtin.
- if (IsFastSmiElementsKind(elements_kind())) {
- __ JumpIfNotSmi(r2, &call_builtin);
- }
-
- // We could be lucky and the elements array could be at the top of new-space.
- // In this case we can just grow it in place by moving the allocation pointer
- // up.
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate);
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate);
-
- const int kAllocationDelta = 4;
- ASSERT(kAllocationDelta >= argc);
- // Load top and check if it is the end of elements.
- __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
- __ add(end_elements, end_elements, Operand(kEndElementsOffset));
- __ mov(r4, Operand(new_space_allocation_top));
- __ ldr(r3, MemOperand(r4));
- __ cmp(end_elements, r3);
- __ b(ne, &call_builtin);
-
- __ mov(r9, Operand(new_space_allocation_limit));
- __ ldr(r9, MemOperand(r9));
- __ add(r3, r3, Operand(kAllocationDelta * kPointerSize));
- __ cmp(r3, r9);
- __ b(hi, &call_builtin);
-
- // We fit and could grow elements.
- // Update new_space_allocation_top.
- __ str(r3, MemOperand(r4));
- // Push the argument.
- __ str(r2, MemOperand(end_elements));
- // Fill the rest with holes.
- __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
- for (int i = 1; i < kAllocationDelta; i++) {
- __ str(r3, MemOperand(end_elements, i * kPointerSize));
- }
-
- // Update elements' and array's sizes.
- __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
- __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
- __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
-
- // Elements are in new space, so write barrier is not required.
- __ Drop(argc + 1);
- __ mov(r0, scratch);
- __ Ret();
-
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
-}
-
-
void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r1 : left
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 4d6ffb9..3679a6f 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -2278,7 +2278,7 @@
Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->generator_result_map());
+ Handle<Map> map(isolate()->native_context()->iterator_result_map());
__ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT);
__ jmp(&allocated);
@@ -4767,7 +4767,8 @@
ExternalReference has_pending_message =
ExternalReference::address_of_has_pending_message(isolate());
__ mov(ip, Operand(has_pending_message));
- __ ldr(r1, MemOperand(ip));
+ STATIC_ASSERT(sizeof(bool) == 1); // NOLINT(runtime/sizeof)
+ __ ldrb(r1, MemOperand(ip));
__ SmiTag(r1);
__ push(r1);
@@ -4793,7 +4794,8 @@
ExternalReference has_pending_message =
ExternalReference::address_of_has_pending_message(isolate());
__ mov(ip, Operand(has_pending_message));
- __ str(r1, MemOperand(ip));
+ STATIC_ASSERT(sizeof(bool) == 1); // NOLINT(runtime/sizeof)
+ __ strb(r1, MemOperand(ip));
__ pop(r1);
ExternalReference pending_message_obj =
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 357c191..b8050d4 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1676,6 +1676,8 @@
LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
HCompareNumericAndBranch* instr) {
+ LInstruction* goto_instr = CheckElideControlInstruction(instr);
+ if (goto_instr != NULL) return goto_instr;
Representation r = instr->representation();
if (r.IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(r));
@@ -1830,9 +1832,16 @@
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
- LOperand* value = UseRegisterOrConstantAtStart(instr->index());
- LOperand* length = UseRegister(instr->length());
- return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
+ if (!FLAG_debug_code && instr->skip_check()) return NULL;
+ LOperand* index = UseRegisterOrConstantAtStart(instr->index());
+ LOperand* length = !index->IsConstantOperand()
+ ? UseRegisterOrConstantAtStart(instr->length())
+ : UseRegisterAtStart(instr->length());
+ LInstruction* result = new(zone()) LBoundsCheck(index, length);
+ if (!FLAG_debug_code || !instr->skip_check()) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 34d98b7..ee695e4 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -4111,7 +4111,7 @@
__ SmiTst(value);
DeoptimizeIf(eq, instr->environment());
- // We know that value is a smi now, so we can omit the check below.
+ // We know now that value is not a smi, so we can omit the check below.
check_needed = OMIT_SMI_CHECK;
}
} else if (representation.IsDouble()) {
@@ -4188,38 +4188,29 @@
}
-void LCodeGen::ApplyCheckIf(Condition condition, LBoundsCheck* check) {
- if (FLAG_debug_code && check->hydrogen()->skip_check()) {
+void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
+ Condition cc = instr->hydrogen()->allow_equality() ? hi : hs;
+ if (instr->index()->IsConstantOperand()) {
+ Operand index = ToOperand(instr->index());
+ Register length = ToRegister(instr->length());
+ __ cmp(length, index);
+ cc = ReverseCondition(cc);
+ } else {
+ Register index = ToRegister(instr->index());
+ Operand length = ToOperand(instr->length());
+ __ cmp(index, length);
+ }
+ if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
Label done;
- __ b(NegateCondition(condition), &done);
+ __ b(NegateCondition(cc), &done);
__ stop("eliminated bounds check failed");
__ bind(&done);
} else {
- DeoptimizeIf(condition, check->environment());
+ DeoptimizeIf(cc, instr->environment());
}
}
-void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
- if (instr->hydrogen()->skip_check()) return;
-
- if (instr->index()->IsConstantOperand()) {
- int constant_index =
- ToInteger32(LConstantOperand::cast(instr->index()));
- if (instr->hydrogen()->length()->representation().IsSmi()) {
- __ mov(ip, Operand(Smi::FromInt(constant_index)));
- } else {
- __ mov(ip, Operand(constant_index));
- }
- __ cmp(ip, ToRegister(instr->length()));
- } else {
- __ cmp(ToRegister(instr->index()), ToRegister(instr->length()));
- }
- Condition condition = instr->hydrogen()->allow_equality() ? hi : hs;
- ApplyCheckIf(condition, instr);
-}
-
-
void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
Register external_pointer = ToRegister(instr->elements());
Register key = no_reg;
@@ -5190,15 +5181,15 @@
__ bind(deferred->check_maps());
}
- UniqueSet<Map> map_set = instr->hydrogen()->map_set();
+ const UniqueSet<Map>* map_set = instr->hydrogen()->map_set();
Label success;
- for (int i = 0; i < map_set.size() - 1; i++) {
- Handle<Map> map = map_set.at(i).handle();
+ for (int i = 0; i < map_set->size() - 1; i++) {
+ Handle<Map> map = map_set->at(i).handle();
__ CompareMap(map_reg, map, &success);
__ b(eq, &success);
}
- Handle<Map> map = map_set.at(map_set.size() - 1).handle();
+ Handle<Map> map = map_set->at(map_set->size() - 1).handle();
__ CompareMap(map_reg, map, &success);
if (instr->hydrogen()->has_migration_target()) {
__ b(ne, deferred->entry());
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 4d1a896..a3fa431 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -264,7 +264,6 @@
LEnvironment* environment,
Deoptimizer::BailoutType bailout_type);
void DeoptimizeIf(Condition condition, LEnvironment* environment);
- void ApplyCheckIf(Condition condition, LBoundsCheck* check);
void AddToTranslation(LEnvironment* environment,
Translation* translation,
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 1633adc..09ccbc3 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -796,6 +796,14 @@
// If needed, restore wanted bits of FPSCR.
Label fpscr_done;
vmrs(scratch);
+ if (emit_debug_code()) {
+ Label rounding_mode_correct;
+ tst(scratch, Operand(kVFPRoundingModeMask));
+ b(eq, &rounding_mode_correct);
+ // Don't call Assert here, since Runtime_Abort could re-enter here.
+ stop("Default rounding mode not set");
+ bind(&rounding_mode_correct);
+ }
tst(scratch, Operand(kVFPDefaultNaNModeControlBit));
b(ne, &fpscr_done);
orr(scratch, scratch, Operand(kVFPDefaultNaNModeControlBit));
@@ -3800,36 +3808,19 @@
void MacroAssembler::ClampDoubleToUint8(Register result_reg,
DwVfpRegister input_reg,
LowDwVfpRegister double_scratch) {
- Label above_zero;
Label done;
- Label in_bounds;
- VFPCompareAndSetFlags(input_reg, 0.0);
- b(gt, &above_zero);
-
- // Double value is less than zero, NaN or Inf, return 0.
- mov(result_reg, Operand::Zero());
- b(al, &done);
-
- // Double value is >= 255, return 255.
- bind(&above_zero);
+ // Handle inputs >= 255 (including +infinity).
Vmov(double_scratch, 255.0, result_reg);
- VFPCompareAndSetFlags(input_reg, double_scratch);
- b(le, &in_bounds);
mov(result_reg, Operand(255));
- b(al, &done);
+ VFPCompareAndSetFlags(input_reg, double_scratch);
+ b(ge, &done);
- // In 0-255 range, round and truncate.
- bind(&in_bounds);
- // Save FPSCR.
- vmrs(ip);
- // Set rounding mode to round to the nearest integer by clearing bits[23:22].
- bic(result_reg, ip, Operand(kVFPRoundingModeMask));
- vmsr(result_reg);
- vcvt_s32_f64(double_scratch.low(), input_reg, kFPSCRRounding);
+ // For inputs < 255 (including negative) vcvt_u32_f64 with round-to-nearest
+ // rounding mode will provide the correct result.
+ vcvt_u32_f64(double_scratch.low(), input_reg, kFPSCRRounding);
vmov(result_reg, double_scratch.low());
- // Restore FPSCR.
- vmsr(ip);
+
bind(&done);
}
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index cbc34e1..d61cfc7 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -1094,7 +1094,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
+ Object* result = Execution::HandleStackGuardInterrupt(isolate);
if (*code_handle != re_code) { // Return address no longer valid
int delta = code_handle->address() - re_code->address();
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index c595e42..3d07d56 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -431,6 +431,22 @@
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
+ HeapType* field_type = descriptors->GetFieldType(descriptor);
+ HeapType::Iterator<Map> it = field_type->Classes();
+ if (!it.Done()) {
+ __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
+ Label do_store;
+ while (true) {
+ __ CompareMap(scratch1, it.Current(), &do_store);
+ it.Advance();
+ if (it.Done()) {
+ __ b(ne, miss_label);
+ break;
+ }
+ __ b(eq, &do_store);
+ }
+ __ bind(&do_store);
+ }
} else if (representation.IsDouble()) {
Label do_store, heap_number;
__ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
@@ -593,6 +609,22 @@
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
+ HeapType* field_type = lookup->GetFieldType();
+ HeapType::Iterator<Map> it = field_type->Classes();
+ if (!it.Done()) {
+ __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
+ Label do_store;
+ while (true) {
+ __ CompareMap(scratch1, it.Current(), &do_store);
+ it.Advance();
+ if (it.Done()) {
+ __ b(ne, miss_label);
+ break;
+ }
+ __ b(eq, &do_store);
+ }
+ __ bind(&do_store);
+ }
} else if (representation.IsDouble()) {
// Load the double storage.
if (index < 0) {
@@ -836,7 +868,9 @@
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
- if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
+ if (type->IsConstant()) {
+ current = Handle<JSObject>::cast(type->AsConstant()->Value());
+ }
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> holder_map(holder->map());
diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc
index b399277..236fe6b 100644
--- a/src/arm64/assembler-arm64.cc
+++ b/src/arm64/assembler-arm64.cc
@@ -273,11 +273,6 @@
bool Operand::NeedsRelocation() const {
if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
-#ifdef DEBUG
- if (!Serializer::enabled()) {
- Serializer::TooLateToEnableNow();
- }
-#endif
return Serializer::enabled();
}
@@ -1970,9 +1965,6 @@
// Don't generate simulator specific code if we are building a snapshot, which
// might be run on real hardware.
if (!Serializer::enabled()) {
-#ifdef DEBUG
- Serializer::TooLateToEnableNow();
-#endif
// The arguments to the debug marker need to be contiguous in memory, so
// make sure we don't try to emit pools.
BlockPoolsScope scope(this);
@@ -2525,11 +2517,6 @@
if (!RelocInfo::IsNone(rmode)) {
// Don't record external references unless the heap will be serialized.
if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
-#ifdef DEBUG
- if (!Serializer::enabled()) {
- Serializer::TooLateToEnableNow();
- }
-#endif
if (!Serializer::enabled() && !emit_debug_code()) {
return;
}
@@ -2831,16 +2818,17 @@
}
-MaybeObject* Assembler::AllocateConstantPool(Heap* heap) {
+Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
// No out-of-line constant pool support.
- UNREACHABLE();
- return NULL;
+ ASSERT(!FLAG_enable_ool_constant_pool);
+ return isolate->factory()->empty_constant_pool_array();
}
void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
// No out-of-line constant pool support.
- UNREACHABLE();
+ ASSERT(!FLAG_enable_ool_constant_pool);
+ return;
}
diff --git a/src/arm64/assembler-arm64.h b/src/arm64/assembler-arm64.h
index 794f87c..5078411 100644
--- a/src/arm64/assembler-arm64.h
+++ b/src/arm64/assembler-arm64.h
@@ -1815,7 +1815,7 @@
void CheckConstPool(bool force_emit, bool require_jump);
// Allocate a constant pool of the correct size for the generated code.
- MaybeObject* AllocateConstantPool(Heap* heap);
+ Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
// Generate the constant pool for the generated code.
void PopulateConstantPool(ConstantPoolArray* constant_pool);
diff --git a/src/arm64/builtins-arm64.cc b/src/arm64/builtins-arm64.cc
index 01ac4cc..3fbe67b 100644
--- a/src/arm64/builtins-arm64.cc
+++ b/src/arm64/builtins-arm64.cc
@@ -1280,7 +1280,7 @@
// There is not enough stack space, so use a builtin to throw an appropriate
// error.
__ Push(function, argc);
- __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
// We should never return from the APPLY_OVERFLOW builtin.
if (__ emit_debug_code()) {
__ Unreachable();
@@ -1400,6 +1400,28 @@
}
+static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
+ Label* stack_overflow) {
+ // ----------- S t a t e -------------
+ // -- x0 : actual number of arguments
+ // -- x1 : function (passed through to callee)
+ // -- x2 : expected number of arguments
+ // -----------------------------------
+ // Check the stack for overflow.
+ // We are not trying to catch interruptions (e.g. debug break and
+ // preemption) here, so the "real stack limit" is checked.
+ Label enough_stack_space;
+ __ LoadRoot(x10, Heap::kRealStackLimitRootIndex);
+ // Make x10 the space we have left. The stack might already be overflowed
+ // here which will cause x10 to become negative.
+ __ Sub(x10, jssp, x10);
+ __ Mov(x11, jssp);
+ // Check if the arguments will overflow the stack.
+ __ Cmp(x10, Operand(x2, LSL, kPointerSizeLog2));
+ __ B(le, stack_overflow);
+}
+
+
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
__ SmiTag(x10, x0);
__ Mov(x11, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
@@ -1433,6 +1455,9 @@
// -- x2 : expected number of arguments
// -----------------------------------
+ Label stack_overflow;
+ ArgumentAdaptorStackCheck(masm, &stack_overflow);
+
Register argc_actual = x0; // Excluding the receiver.
Register argc_expected = x2; // Excluding the receiver.
Register function = x1;
@@ -1552,6 +1577,14 @@
// Call the entry point without adapting the arguments.
__ Bind(&dont_adapt_arguments);
__ Jump(code_entry);
+
+ __ Bind(&stack_overflow);
+ {
+ FrameScope frame(masm, StackFrame::MANUAL);
+ EnterArgumentsAdaptorFrame(masm);
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
+ __ Brk(0);
+ }
}
diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc
index 9bd2dca..1275882 100644
--- a/src/arm64/code-stubs-arm64.cc
+++ b/src/arm64/code-stubs-arm64.cc
@@ -1477,186 +1477,6 @@
}
-void CEntryStub::GenerateCore(MacroAssembler* masm,
- Label* throw_normal,
- Label* throw_termination,
- bool do_gc,
- bool always_allocate) {
- // x0 : Result parameter for PerformGC, if do_gc is true.
- // x21 : argv
- // x22 : argc
- // x23 : target
- //
- // The stack (on entry) holds the arguments and the receiver, with the
- // receiver at the highest address:
- //
- // argv[8]: receiver
- // argv -> argv[0]: arg[argc-2]
- // ... ...
- // argv[...]: arg[1]
- // argv[...]: arg[0]
- //
- // Immediately below (after) this is the exit frame, as constructed by
- // EnterExitFrame:
- // fp[8]: CallerPC (lr)
- // fp -> fp[0]: CallerFP (old fp)
- // fp[-8]: Space reserved for SPOffset.
- // fp[-16]: CodeObject()
- // csp[...]: Saved doubles, if saved_doubles is true.
- // csp[32]: Alignment padding, if necessary.
- // csp[24]: Preserved x23 (used for target).
- // csp[16]: Preserved x22 (used for argc).
- // csp[8]: Preserved x21 (used for argv).
- // csp -> csp[0]: Space reserved for the return address.
- //
- // After a successful call, the exit frame, preserved registers (x21-x23) and
- // the arguments (including the receiver) are dropped or popped as
- // appropriate. The stub then returns.
- //
- // After an unsuccessful call, the exit frame and suchlike are left
- // untouched, and the stub either throws an exception by jumping to one of
- // the provided throw_ labels, or it falls through. The failure details are
- // passed through in x0.
- ASSERT(csp.Is(__ StackPointer()));
-
- Isolate* isolate = masm->isolate();
-
- const Register& argv = x21;
- const Register& argc = x22;
- const Register& target = x23;
-
- if (do_gc) {
- // Call Runtime::PerformGC, passing x0 (the result parameter for
- // PerformGC) and x1 (the isolate).
- __ Mov(x1, ExternalReference::isolate_address(masm->isolate()));
- __ CallCFunction(
- ExternalReference::perform_gc_function(isolate), 2, 0);
- }
-
- ExternalReference scope_depth =
- ExternalReference::heap_always_allocate_scope_depth(isolate);
- if (always_allocate) {
- __ Mov(x10, Operand(scope_depth));
- __ Ldr(x11, MemOperand(x10));
- __ Add(x11, x11, 1);
- __ Str(x11, MemOperand(x10));
- }
-
- // Prepare AAPCS64 arguments to pass to the builtin.
- __ Mov(x0, argc);
- __ Mov(x1, argv);
- __ Mov(x2, ExternalReference::isolate_address(isolate));
-
- // Store the return address on the stack, in the space previously allocated
- // by EnterExitFrame. The return address is queried by
- // ExitFrame::GetStateForFramePointer.
- Label return_location;
- __ Adr(x12, &return_location);
- __ Poke(x12, 0);
- if (__ emit_debug_code()) {
- // Verify that the slot below fp[kSPOffset]-8 points to the return location
- // (currently in x12).
- UseScratchRegisterScope temps(masm);
- Register temp = temps.AcquireX();
- __ Ldr(temp, MemOperand(fp, ExitFrameConstants::kSPOffset));
- __ Ldr(temp, MemOperand(temp, -static_cast<int64_t>(kXRegSize)));
- __ Cmp(temp, x12);
- __ Check(eq, kReturnAddressNotFoundInFrame);
- }
-
- // Call the builtin.
- __ Blr(target);
- __ Bind(&return_location);
- const Register& result = x0;
-
- if (always_allocate) {
- __ Mov(x10, Operand(scope_depth));
- __ Ldr(x11, MemOperand(x10));
- __ Sub(x11, x11, 1);
- __ Str(x11, MemOperand(x10));
- }
-
- // x0 result The return code from the call.
- // x21 argv
- // x22 argc
- // x23 target
- //
- // If all of the result bits matching kFailureTagMask are '1', the result is
- // a failure. Otherwise, it's an ordinary tagged object and the call was a
- // success.
- Label failure;
- __ And(x10, result, kFailureTagMask);
- __ Cmp(x10, kFailureTagMask);
- __ B(&failure, eq);
-
- // The call succeeded, so unwind the stack and return.
-
- // Restore callee-saved registers x21-x23.
- __ Mov(x11, argc);
-
- __ Peek(argv, 1 * kPointerSize);
- __ Peek(argc, 2 * kPointerSize);
- __ Peek(target, 3 * kPointerSize);
-
- __ LeaveExitFrame(save_doubles_, x10, true);
- ASSERT(jssp.Is(__ StackPointer()));
- // Pop or drop the remaining stack slots and return from the stub.
- // jssp[24]: Arguments array (of size argc), including receiver.
- // jssp[16]: Preserved x23 (used for target).
- // jssp[8]: Preserved x22 (used for argc).
- // jssp[0]: Preserved x21 (used for argv).
- __ Drop(x11);
- __ Ret();
-
- // The stack pointer is still csp if we aren't returning, and the frame
- // hasn't changed (except for the return address).
- __ SetStackPointer(csp);
-
- __ Bind(&failure);
- // The call failed, so check if we need to throw an exception, and fall
- // through (to retry) otherwise.
-
- Label retry;
- // x0 result The return code from the call, including the failure
- // code and details.
- // x21 argv
- // x22 argc
- // x23 target
- // Refer to the Failure class for details of the bit layout.
- STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
- __ Tst(result, kFailureTypeTagMask << kFailureTagSize);
- __ B(eq, &retry); // RETRY_AFTER_GC
-
- // Retrieve the pending exception.
- const Register& exception = result;
- const Register& exception_address = x11;
- __ Mov(exception_address,
- Operand(ExternalReference(Isolate::kPendingExceptionAddress,
- isolate)));
- __ Ldr(exception, MemOperand(exception_address));
-
- // Clear the pending exception.
- __ Mov(x10, Operand(isolate->factory()->the_hole_value()));
- __ Str(x10, MemOperand(exception_address));
-
- // x0 exception The exception descriptor.
- // x21 argv
- // x22 argc
- // x23 target
-
- // Special handling of termination exceptions, which are uncatchable by
- // JavaScript code.
- __ Cmp(exception, Operand(isolate->factory()->termination_exception()));
- __ B(eq, throw_termination);
-
- // Handle normal exception.
- __ B(throw_normal);
-
- __ Bind(&retry);
- // The result (x0) is passed through as the next PerformGC parameter.
-}
-
-
void CEntryStub::Generate(MacroAssembler* masm) {
// The Abort mechanism relies on CallRuntime, which in turn relies on
// CEntryStub, so until this stub has been generated, we have to use a
@@ -1726,63 +1546,146 @@
__ Mov(target, target_input);
__ Mov(argv, temp_argv);
- Label throw_normal;
- Label throw_termination;
+ // x21 : argv
+ // x22 : argc
+ // x23 : call target
+ //
+ // The stack (on entry) holds the arguments and the receiver, with the
+ // receiver at the highest address:
+ //
+ // argv[8]: receiver
+ // argv -> argv[0]: arg[argc-2]
+ // ... ...
+ // argv[...]: arg[1]
+ // argv[...]: arg[0]
+ //
+ // Immediately below (after) this is the exit frame, as constructed by
+ // EnterExitFrame:
+ // fp[8]: CallerPC (lr)
+ // fp -> fp[0]: CallerFP (old fp)
+ // fp[-8]: Space reserved for SPOffset.
+ // fp[-16]: CodeObject()
+ // csp[...]: Saved doubles, if saved_doubles is true.
+ // csp[32]: Alignment padding, if necessary.
+ // csp[24]: Preserved x23 (used for target).
+ // csp[16]: Preserved x22 (used for argc).
+ // csp[8]: Preserved x21 (used for argv).
+ // csp -> csp[0]: Space reserved for the return address.
+ //
+ // After a successful call, the exit frame, preserved registers (x21-x23) and
+ // the arguments (including the receiver) are dropped or popped as
+ // appropriate. The stub then returns.
+ //
+ // After an unsuccessful call, the exit frame and suchlike are left
+ // untouched, and the stub either throws an exception by jumping to one of
+ // the exception_returned label.
- // Call the runtime function.
- GenerateCore(masm,
- &throw_normal,
- &throw_termination,
- false,
- false);
+ ASSERT(csp.Is(__ StackPointer()));
- // If successful, the previous GenerateCore will have returned to the
- // calling code. Otherwise, we fall through into the following.
+ Isolate* isolate = masm->isolate();
- // Do space-specific GC and retry runtime call.
- GenerateCore(masm,
- &throw_normal,
- &throw_termination,
- true,
- false);
+ // Prepare AAPCS64 arguments to pass to the builtin.
+ __ Mov(x0, argc);
+ __ Mov(x1, argv);
+ __ Mov(x2, ExternalReference::isolate_address(isolate));
- // Do full GC and retry runtime call one final time.
- __ Mov(x0, reinterpret_cast<uint64_t>(Failure::InternalError()));
- GenerateCore(masm,
- &throw_normal,
- &throw_termination,
- true,
- true);
+ Label return_location;
+ __ Adr(x12, &return_location);
+ __ Poke(x12, 0);
- { FrameScope scope(masm, StackFrame::MANUAL);
- __ CallCFunction(
- ExternalReference::out_of_memory_function(masm->isolate()), 0);
+ if (__ emit_debug_code()) {
+ // Verify that the slot below fp[kSPOffset]-8 points to the return location
+ // (currently in x12).
+ UseScratchRegisterScope temps(masm);
+ Register temp = temps.AcquireX();
+ __ Ldr(temp, MemOperand(fp, ExitFrameConstants::kSPOffset));
+ __ Ldr(temp, MemOperand(temp, -static_cast<int64_t>(kXRegSize)));
+ __ Cmp(temp, x12);
+ __ Check(eq, kReturnAddressNotFoundInFrame);
}
+ // Call the builtin.
+ __ Blr(target);
+ __ Bind(&return_location);
+
+ // x0 result The return code from the call.
+ // x21 argv
+ // x22 argc
+ // x23 target
+ const Register& result = x0;
+
+ // Check result for exception sentinel.
+ Label exception_returned;
+ __ CompareRoot(result, Heap::kExceptionRootIndex);
+ __ B(eq, &exception_returned);
+
+ // The call succeeded, so unwind the stack and return.
+
+ // Restore callee-saved registers x21-x23.
+ __ Mov(x11, argc);
+
+ __ Peek(argv, 1 * kPointerSize);
+ __ Peek(argc, 2 * kPointerSize);
+ __ Peek(target, 3 * kPointerSize);
+
+ __ LeaveExitFrame(save_doubles_, x10, true);
+ ASSERT(jssp.Is(__ StackPointer()));
+ // Pop or drop the remaining stack slots and return from the stub.
+ // jssp[24]: Arguments array (of size argc), including receiver.
+ // jssp[16]: Preserved x23 (used for target).
+ // jssp[8]: Preserved x22 (used for argc).
+ // jssp[0]: Preserved x21 (used for argv).
+ __ Drop(x11);
+ __ Ret();
+
+ // The stack pointer is still csp if we aren't returning, and the frame
+ // hasn't changed (except for the return address).
+ __ SetStackPointer(csp);
+
+ // Handling of exception.
+ __ Bind(&exception_returned);
+
+ // Retrieve the pending exception.
+ ExternalReference pending_exception_address(
+ Isolate::kPendingExceptionAddress, isolate);
+ const Register& exception = result;
+ const Register& exception_address = x11;
+ __ Mov(exception_address, Operand(pending_exception_address));
+ __ Ldr(exception, MemOperand(exception_address));
+
+ // Clear the pending exception.
+ __ Mov(x10, Operand(isolate->factory()->the_hole_value()));
+ __ Str(x10, MemOperand(exception_address));
+
+ // x0 exception The exception descriptor.
+ // x21 argv
+ // x22 argc
+ // x23 target
+
+ // Special handling of termination exceptions, which are uncatchable by
+ // JavaScript code.
+ Label throw_termination_exception;
+ __ Cmp(exception, Operand(isolate->factory()->termination_exception()));
+ __ B(eq, &throw_termination_exception);
+
// We didn't execute a return case, so the stack frame hasn't been updated
// (except for the return address slot). However, we don't need to initialize
// jssp because the throw method will immediately overwrite it when it
// unwinds the stack.
__ SetStackPointer(jssp);
- // Throw exceptions.
- // If we throw an exception, we can end up re-entering CEntryStub before we
- // pop the exit frame, so need to ensure that x21-x23 contain GC-safe values
- // here.
-
- __ Bind(&throw_termination);
- ASM_LOCATION("Throw termination");
- __ Mov(argv, 0);
- __ Mov(argc, 0);
- __ Mov(target, 0);
- __ ThrowUncatchable(x0, x10, x11, x12, x13);
-
- __ Bind(&throw_normal);
ASM_LOCATION("Throw normal");
__ Mov(argv, 0);
__ Mov(argc, 0);
__ Mov(target, 0);
__ Throw(x0, x10, x11, x12, x13);
+
+ __ Bind(&throw_termination_exception);
+ ASM_LOCATION("Throw termination");
+ __ Mov(argv, 0);
+ __ Mov(argc, 0);
+ __ Mov(target, 0);
+ __ ThrowUncatchable(x0, x10, x11, x12, x13);
}
@@ -1882,7 +1785,7 @@
isolate)));
}
__ Str(code_entry, MemOperand(x10));
- __ Mov(x0, Operand(reinterpret_cast<int64_t>(Failure::Exception())));
+ __ LoadRoot(x0, Heap::kExceptionRootIndex);
__ B(&exit);
// Invoke: Link this frame into the handler chain. There's only one
@@ -4405,215 +4308,6 @@
}
-void ArrayPushStub::Generate(MacroAssembler* masm) {
- Register receiver = x0;
-
- int argc = arguments_count();
-
- if (argc == 0) {
- // Nothing to do, just return the length.
- __ Ldr(x0, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ Drop(argc + 1);
- __ Ret();
- return;
- }
-
- Isolate* isolate = masm->isolate();
-
- if (argc != 1) {
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- Label call_builtin, attempt_to_grow_elements, with_write_barrier;
-
- Register elements_length = x8;
- Register length = x7;
- Register elements = x6;
- Register end_elements = x5;
- Register value = x4;
- // Get the elements array of the object.
- __ Ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
-
- if (IsFastSmiOrObjectElementsKind(elements_kind())) {
- // Check that the elements are in fast mode and writable.
- __ CheckMap(elements,
- x10,
- Heap::kFixedArrayMapRootIndex,
- &call_builtin,
- DONT_DO_SMI_CHECK);
- }
-
- // Get the array's length and calculate new length.
- __ Ldr(length, FieldMemOperand(receiver, JSArray::kLengthOffset));
- STATIC_ASSERT(kSmiTag == 0);
- __ Add(length, length, Smi::FromInt(argc));
-
- // Check if we could survive without allocation.
- __ Ldr(elements_length,
- FieldMemOperand(elements, FixedArray::kLengthOffset));
- __ Cmp(length, elements_length);
-
- const int kEndElementsOffset =
- FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
-
- if (IsFastSmiOrObjectElementsKind(elements_kind())) {
- __ B(gt, &attempt_to_grow_elements);
-
- // Check if value is a smi.
- __ Peek(value, (argc - 1) * kPointerSize);
- __ JumpIfNotSmi(value, &with_write_barrier);
-
- // Store the value.
- // We may need a register containing the address end_elements below,
- // so write back the value in end_elements.
- __ Add(end_elements, elements,
- Operand::UntagSmiAndScale(length, kPointerSizeLog2));
- __ Str(value, MemOperand(end_elements, kEndElementsOffset, PreIndex));
- } else {
- __ B(gt, &call_builtin);
-
- __ Peek(value, (argc - 1) * kPointerSize);
- __ StoreNumberToDoubleElements(value, length, elements, x10, d0, d1,
- &call_builtin, argc * kDoubleSize);
- }
-
- // Save new length.
- __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset));
-
- // Return length.
- __ Drop(argc + 1);
- __ Mov(x0, length);
- __ Ret();
-
- if (IsFastDoubleElementsKind(elements_kind())) {
- __ Bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- __ Bind(&with_write_barrier);
-
- if (IsFastSmiElementsKind(elements_kind())) {
- if (FLAG_trace_elements_transitions) {
- __ B(&call_builtin);
- }
-
- __ Ldr(x10, FieldMemOperand(value, HeapObject::kMapOffset));
- __ JumpIfHeapNumber(x10, &call_builtin);
-
- ElementsKind target_kind = IsHoleyElementsKind(elements_kind())
- ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
- __ Ldr(x10, GlobalObjectMemOperand());
- __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kNativeContextOffset));
- __ Ldr(x10, ContextMemOperand(x10, Context::JS_ARRAY_MAPS_INDEX));
- const int header_size = FixedArrayBase::kHeaderSize;
- // Verify that the object can be transitioned in place.
- const int origin_offset = header_size + elements_kind() * kPointerSize;
- __ ldr(x11, FieldMemOperand(receiver, origin_offset));
- __ ldr(x12, FieldMemOperand(x10, HeapObject::kMapOffset));
- __ cmp(x11, x12);
- __ B(ne, &call_builtin);
-
- const int target_offset = header_size + target_kind * kPointerSize;
- __ Ldr(x10, FieldMemOperand(x10, target_offset));
- __ Mov(x11, receiver);
- ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
- masm, DONT_TRACK_ALLOCATION_SITE, NULL);
- }
-
- // Save new length.
- __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset));
-
- // Store the value.
- // We may need a register containing the address end_elements below,
- // so write back the value in end_elements.
- __ Add(end_elements, elements,
- Operand::UntagSmiAndScale(length, kPointerSizeLog2));
- __ Str(value, MemOperand(end_elements, kEndElementsOffset, PreIndex));
-
- __ RecordWrite(elements,
- end_elements,
- value,
- kLRHasNotBeenSaved,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- __ Drop(argc + 1);
- __ Mov(x0, length);
- __ Ret();
-
- __ Bind(&attempt_to_grow_elements);
-
- if (!FLAG_inline_new) {
- __ B(&call_builtin);
- }
-
- Register argument = x2;
- __ Peek(argument, (argc - 1) * kPointerSize);
- // Growing elements that are SMI-only requires special handling in case
- // the new element is non-Smi. For now, delegate to the builtin.
- if (IsFastSmiElementsKind(elements_kind())) {
- __ JumpIfNotSmi(argument, &call_builtin);
- }
-
- // We could be lucky and the elements array could be at the top of new-space.
- // In this case we can just grow it in place by moving the allocation pointer
- // up.
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate);
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate);
-
- const int kAllocationDelta = 4;
- ASSERT(kAllocationDelta >= argc);
- Register allocation_top_addr = x5;
- Register allocation_top = x9;
- // Load top and check if it is the end of elements.
- __ Add(end_elements, elements,
- Operand::UntagSmiAndScale(length, kPointerSizeLog2));
- __ Add(end_elements, end_elements, kEndElementsOffset);
- __ Mov(allocation_top_addr, new_space_allocation_top);
- __ Ldr(allocation_top, MemOperand(allocation_top_addr));
- __ Cmp(end_elements, allocation_top);
- __ B(ne, &call_builtin);
-
- __ Mov(x10, new_space_allocation_limit);
- __ Ldr(x10, MemOperand(x10));
- __ Add(allocation_top, allocation_top, kAllocationDelta * kPointerSize);
- __ Cmp(allocation_top, x10);
- __ B(hi, &call_builtin);
-
- // We fit and could grow elements.
- // Update new_space_allocation_top.
- __ Str(allocation_top, MemOperand(allocation_top_addr));
- // Push the argument.
- __ Str(argument, MemOperand(end_elements));
- // Fill the rest with holes.
- __ LoadRoot(x10, Heap::kTheHoleValueRootIndex);
- ASSERT(kAllocationDelta == 4);
- __ Stp(x10, x10, MemOperand(end_elements, 1 * kPointerSize));
- __ Stp(x10, x10, MemOperand(end_elements, 3 * kPointerSize));
-
- // Update elements' and array's sizes.
- __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ Add(elements_length, elements_length, Smi::FromInt(kAllocationDelta));
- __ Str(elements_length,
- FieldMemOperand(elements, FixedArray::kLengthOffset));
-
- // Elements are in new space, so write barrier is not required.
- __ Drop(argc + 1);
- __ Mov(x0, length);
- __ Ret();
-
- __ Bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
-}
-
-
void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x1 : left
diff --git a/src/arm64/full-codegen-arm64.cc b/src/arm64/full-codegen-arm64.cc
index 5679ccd..76bb1b5 100644
--- a/src/arm64/full-codegen-arm64.cc
+++ b/src/arm64/full-codegen-arm64.cc
@@ -4706,7 +4706,7 @@
Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->generator_result_map());
+ Handle<Map> map(isolate()->native_context()->iterator_result_map());
// Allocate and populate an object with this form: { value: VAL, done: DONE }
@@ -4821,8 +4821,9 @@
ExternalReference has_pending_message =
ExternalReference::address_of_has_pending_message(isolate());
+ STATIC_ASSERT(sizeof(bool) == 1); // NOLINT(runtime/sizeof)
__ Mov(x11, has_pending_message);
- __ Ldr(x11, MemOperand(x11));
+ __ Ldrb(x11, MemOperand(x11));
__ SmiTag(x11);
__ Push(x10, x11);
@@ -4850,7 +4851,8 @@
ExternalReference has_pending_message =
ExternalReference::address_of_has_pending_message(isolate());
__ Mov(x13, has_pending_message);
- __ Str(x11, MemOperand(x13));
+ STATIC_ASSERT(sizeof(bool) == 1); // NOLINT(runtime/sizeof)
+ __ Strb(x11, MemOperand(x13));
ExternalReference pending_message_obj =
ExternalReference::address_of_pending_message_obj(isolate());
diff --git a/src/arm64/lithium-arm64.cc b/src/arm64/lithium-arm64.cc
index adc2b5c..812fe12 100644
--- a/src/arm64/lithium-arm64.cc
+++ b/src/arm64/lithium-arm64.cc
@@ -949,9 +949,16 @@
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
- LOperand* value = UseRegisterOrConstantAtStart(instr->index());
- LOperand* length = UseRegister(instr->length());
- return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
+ if (!FLAG_debug_code && instr->skip_check()) return NULL;
+ LOperand* index = UseRegisterOrConstantAtStart(instr->index());
+ LOperand* length = !index->IsConstantOperand()
+ ? UseRegisterOrConstantAtStart(instr->length())
+ : UseRegisterAtStart(instr->length());
+ LInstruction* result = new(zone()) LBoundsCheck(index, length);
+ if (!FLAG_debug_code || !instr->skip_check()) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1244,8 +1251,9 @@
LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
HCompareNumericAndBranch* instr) {
+ LInstruction* goto_instr = CheckElideControlInstruction(instr);
+ if (goto_instr != NULL) return goto_instr;
Representation r = instr->representation();
-
if (r.IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(r));
ASSERT(instr->right()->representation().Equals(r));
@@ -1658,9 +1666,10 @@
ASSERT(instr->key()->representation().IsSmiOrInteger32());
ElementsKind elements_kind = instr->elements_kind();
LOperand* elements = UseRegister(instr->elements());
- LOperand* key = UseRegisterOrConstantAtStart(instr->key());
if (!instr->is_typed_elements()) {
+ LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+
if (instr->representation().IsDouble()) {
LOperand* temp = (!instr->key()->IsConstant() ||
instr->RequiresHoleCheck())
@@ -1688,6 +1697,7 @@
(instr->representation().IsDouble() &&
IsDoubleOrFloatElementsKind(instr->elements_kind())));
+ LOperand* key = UseRegisterOrConstant(instr->key());
LOperand* temp = instr->key()->IsConstant() ? NULL : TempRegister();
LInstruction* result = DefineAsRegister(
new(zone()) LLoadKeyedExternal(elements, key, temp));
@@ -2180,7 +2190,6 @@
LOperand* temp = NULL;
LOperand* elements = NULL;
LOperand* val = NULL;
- LOperand* key = UseRegisterOrConstantAtStart(instr->key());
if (!instr->is_typed_elements() &&
instr->value()->representation().IsTagged() &&
@@ -2204,16 +2213,19 @@
instr->elements()->representation().IsTagged()) ||
(instr->is_external() &&
instr->elements()->representation().IsExternal()));
+ LOperand* key = UseRegisterOrConstant(instr->key());
return new(zone()) LStoreKeyedExternal(elements, key, val, temp);
} else if (instr->value()->representation().IsDouble()) {
ASSERT(instr->elements()->representation().IsTagged());
+ LOperand* key = UseRegisterOrConstantAtStart(instr->key());
return new(zone()) LStoreKeyedFixedDouble(elements, key, val, temp);
} else {
ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->value()->representation().IsSmiOrTagged() ||
instr->value()->representation().IsInteger32());
+ LOperand* key = UseRegisterOrConstantAtStart(instr->key());
return new(zone()) LStoreKeyedFixed(elements, key, val, temp);
}
}
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc
index 1fb5b76..969af2b 100644
--- a/src/arm64/lithium-codegen-arm64.cc
+++ b/src/arm64/lithium-codegen-arm64.cc
@@ -1775,39 +1775,28 @@
}
-void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) {
- if (FLAG_debug_code && check->hydrogen()->skip_check()) {
+void LCodeGen::DoBoundsCheck(LBoundsCheck *instr) {
+ Condition cc = instr->hydrogen()->allow_equality() ? hi : hs;
+ ASSERT(instr->hydrogen()->index()->representation().IsInteger32());
+ ASSERT(instr->hydrogen()->length()->representation().IsInteger32());
+ if (instr->index()->IsConstantOperand()) {
+ Operand index = ToOperand32I(instr->index());
+ Register length = ToRegister32(instr->length());
+ __ Cmp(length, index);
+ cc = ReverseConditionForCmp(cc);
+ } else {
+ Register index = ToRegister32(instr->index());
+ Operand length = ToOperand32I(instr->length());
+ __ Cmp(index, length);
+ }
+ if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
__ Assert(InvertCondition(cc), kEliminatedBoundsCheckFailed);
} else {
- DeoptimizeIf(cc, check->environment());
+ DeoptimizeIf(cc, instr->environment());
}
}
-void LCodeGen::DoBoundsCheck(LBoundsCheck *instr) {
- if (instr->hydrogen()->skip_check()) return;
-
- ASSERT(instr->hydrogen()->length()->representation().IsInteger32());
- Register length = ToRegister32(instr->length());
-
- if (instr->index()->IsConstantOperand()) {
- int constant_index =
- ToInteger32(LConstantOperand::cast(instr->index()));
-
- if (instr->hydrogen()->length()->representation().IsSmi()) {
- __ Cmp(length, Smi::FromInt(constant_index));
- } else {
- __ Cmp(length, constant_index);
- }
- } else {
- ASSERT(instr->hydrogen()->index()->representation().IsInteger32());
- __ Cmp(length, ToRegister32(instr->index()));
- }
- Condition condition = instr->hydrogen()->allow_equality() ? lo : ls;
- ApplyCheckIf(condition, instr);
-}
-
-
void LCodeGen::DoBranch(LBranch* instr) {
Representation r = instr->hydrogen()->value()->representation();
Label* true_label = instr->TrueLabel(chunk_);
@@ -2135,14 +2124,14 @@
__ Bind(deferred->check_maps());
}
- UniqueSet<Map> map_set = instr->hydrogen()->map_set();
+ const UniqueSet<Map>* map_set = instr->hydrogen()->map_set();
Label success;
- for (int i = 0; i < map_set.size() - 1; i++) {
- Handle<Map> map = map_set.at(i).handle();
+ for (int i = 0; i < map_set->size() - 1; i++) {
+ Handle<Map> map = map_set->at(i).handle();
__ CompareMap(map_reg, map);
__ B(eq, &success);
}
- Handle<Map> map = map_set.at(map_set.size() - 1).handle();
+ Handle<Map> map = map_set->at(map_set->size() - 1).handle();
__ CompareMap(map_reg, map);
// We didn't match a map.
@@ -3344,51 +3333,28 @@
ElementsKind elements_kind,
int additional_index) {
int element_size_shift = ElementsKindToShiftSize(elements_kind);
- int additional_offset = IsFixedTypedArrayElementsKind(elements_kind)
- ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
- : 0;
+ int additional_offset = additional_index << element_size_shift;
+ if (IsFixedTypedArrayElementsKind(elements_kind)) {
+ additional_offset += FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
+ }
if (key_is_constant) {
- int base_offset = ((constant_key + additional_index) << element_size_shift);
- return MemOperand(base, base_offset + additional_offset);
+ int key_offset = constant_key << element_size_shift;
+ return MemOperand(base, key_offset + additional_offset);
}
- if (additional_index == 0) {
- if (key_is_smi) {
- // Key is smi: untag, and scale by element size.
- __ Add(scratch, base, Operand::UntagSmiAndScale(key, element_size_shift));
- return MemOperand(scratch, additional_offset);
- } else {
- // Key is not smi, and element size is not byte: scale by element size.
- if (additional_offset == 0) {
- return MemOperand(base, key, SXTW, element_size_shift);
- } else {
- __ Add(scratch, base, Operand(key, SXTW, element_size_shift));
- return MemOperand(scratch, additional_offset);
- }
- }
- } else {
- // TODO(all): Try to combine these cases a bit more intelligently.
- if (additional_offset == 0) {
- if (key_is_smi) {
- __ SmiUntag(scratch, key);
- __ Add(scratch.W(), scratch.W(), additional_index);
- } else {
- __ Add(scratch.W(), key.W(), additional_index);
- }
- return MemOperand(base, scratch, LSL, element_size_shift);
- } else {
- if (key_is_smi) {
- __ Add(scratch, base,
- Operand::UntagSmiAndScale(key, element_size_shift));
- } else {
- __ Add(scratch, base, Operand(key, SXTW, element_size_shift));
- }
- return MemOperand(
- scratch,
- (additional_index << element_size_shift) + additional_offset);
- }
+ if (key_is_smi) {
+ __ Add(scratch, base, Operand::UntagSmiAndScale(key, element_size_shift));
+ return MemOperand(scratch, additional_offset);
}
+
+ if (additional_offset == 0) {
+ return MemOperand(base, key, SXTW, element_size_shift);
+ }
+
+ ASSERT(!AreAliased(scratch, key));
+ __ Add(scratch, base, additional_offset);
+ return MemOperand(scratch, key, SXTW, element_size_shift);
}
@@ -4684,13 +4650,13 @@
return FieldMemOperand(string, SeqString::kHeaderSize + offset);
}
+ __ Add(temp, string, SeqString::kHeaderSize - kHeapObjectTag);
if (encoding == String::ONE_BYTE_ENCODING) {
- __ Add(temp, string, Operand(ToRegister32(index), SXTW));
+ return MemOperand(temp, ToRegister32(index), SXTW);
} else {
STATIC_ASSERT(kUC16Size == 2);
- __ Add(temp, string, Operand(ToRegister32(index), SXTW, 1));
+ return MemOperand(temp, ToRegister32(index), SXTW, 1);
}
- return FieldMemOperand(temp, SeqString::kHeaderSize);
}
@@ -5265,7 +5231,7 @@
!instr->hydrogen()->value()->type().IsHeapObject()) {
DeoptimizeIfSmi(value, instr->environment());
- // We know that value is a smi now, so we can omit the check below.
+ // We know now that value is not a smi, so we can omit the check below.
check_needed = OMIT_SMI_CHECK;
}
@@ -5421,8 +5387,8 @@
__ Cmp(char_code, String::kMaxOneByteCharCode);
__ B(hi, deferred->entry());
__ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
- __ Add(result, result, Operand(char_code, SXTW, kPointerSizeLog2));
- __ Ldr(result, FieldMemOperand(result, FixedArray::kHeaderSize));
+ __ Add(result, result, FixedArray::kHeaderSize - kHeapObjectTag);
+ __ Ldr(result, MemOperand(result, char_code, SXTW, kPointerSizeLog2));
__ CompareRoot(result, Heap::kUndefinedValueRootIndex);
__ B(eq, deferred->entry());
__ Bind(deferred->exit());
diff --git a/src/arm64/lithium-codegen-arm64.h b/src/arm64/lithium-codegen-arm64.h
index e06f05c..4c9d35a 100644
--- a/src/arm64/lithium-codegen-arm64.h
+++ b/src/arm64/lithium-codegen-arm64.h
@@ -243,7 +243,6 @@
void DeoptimizeIfMinusZero(DoubleRegister input, LEnvironment* environment);
void DeoptimizeIfBitSet(Register rt, int bit, LEnvironment* environment);
void DeoptimizeIfBitClear(Register rt, int bit, LEnvironment* environment);
- void ApplyCheckIf(Condition cc, LBoundsCheck* check);
MemOperand PrepareKeyedExternalArrayOperand(Register key,
Register base,
diff --git a/src/arm64/regexp-macro-assembler-arm64.cc b/src/arm64/regexp-macro-assembler-arm64.cc
index decf314..81f4617 100644
--- a/src/arm64/regexp-macro-assembler-arm64.cc
+++ b/src/arm64/regexp-macro-assembler-arm64.cc
@@ -1338,7 +1338,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
+ Object* result = Execution::HandleStackGuardInterrupt(isolate);
if (*code_handle != re_code) { // Return address no longer valid
int delta = code_handle->address() - re_code->address();
diff --git a/src/arm64/stub-cache-arm64.cc b/src/arm64/stub-cache-arm64.cc
index aed9af9..b46d813 100644
--- a/src/arm64/stub-cache-arm64.cc
+++ b/src/arm64/stub-cache-arm64.cc
@@ -393,6 +393,22 @@
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
+ HeapType* field_type = descriptors->GetFieldType(descriptor);
+ HeapType::Iterator<Map> it = field_type->Classes();
+ if (!it.Done()) {
+ __ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
+ Label do_store;
+ while (true) {
+ __ CompareMap(scratch1, it.Current());
+ it.Advance();
+ if (it.Done()) {
+ __ B(ne, miss_label);
+ break;
+ }
+ __ B(eq, &do_store);
+ }
+ __ Bind(&do_store);
+ }
} else if (representation.IsDouble()) {
UseScratchRegisterScope temps(masm);
DoubleRegister temp_double = temps.AcquireD();
@@ -542,6 +558,22 @@
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
+ HeapType* field_type = lookup->GetFieldType();
+ HeapType::Iterator<Map> it = field_type->Classes();
+ if (!it.Done()) {
+ __ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
+ Label do_store;
+ while (true) {
+ __ CompareMap(scratch1, it.Current());
+ it.Advance();
+ if (it.Done()) {
+ __ B(ne, miss_label);
+ break;
+ }
+ __ B(eq, &do_store);
+ }
+ __ Bind(&do_store);
+ }
} else if (representation.IsDouble()) {
UseScratchRegisterScope temps(masm);
DoubleRegister temp_double = temps.AcquireD();
@@ -788,7 +820,7 @@
Handle<JSObject> current = Handle<JSObject>::null();
if (type->IsConstant()) {
- current = Handle<JSObject>::cast(type->AsConstant());
+ current = Handle<JSObject>::cast(type->AsConstant()->Value());
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
diff --git a/src/array-iterator.js b/src/array-iterator.js
index 3af659d..10116b1 100644
--- a/src/array-iterator.js
+++ b/src/array-iterator.js
@@ -31,11 +31,6 @@
// in runtime.js:
// var $Array = global.Array;
-var ARRAY_ITERATOR_KIND_KEYS = 1;
-var ARRAY_ITERATOR_KIND_VALUES = 2;
-var ARRAY_ITERATOR_KIND_ENTRIES = 3;
-// The spec draft also has "sparse" but it is never used.
-
var arrayIteratorObjectSymbol = GLOBAL_PRIVATE("ArrayIterator#object");
var arrayIteratorNextIndexSymbol = GLOBAL_PRIVATE("ArrayIterator#next");
var arrayIterationKindSymbol = GLOBAL_PRIVATE("ArrayIterator#kind");
@@ -79,25 +74,25 @@
SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, index + 1);
- if (itemKind == ARRAY_ITERATOR_KIND_VALUES)
+ if (itemKind == ITERATOR_KIND_VALUES)
return CreateIteratorResultObject(array[index], false);
- if (itemKind == ARRAY_ITERATOR_KIND_ENTRIES)
+ if (itemKind == ITERATOR_KIND_ENTRIES)
return CreateIteratorResultObject([index, array[index]], false);
return CreateIteratorResultObject(index, false);
}
function ArrayEntries() {
- return CreateArrayIterator(this, ARRAY_ITERATOR_KIND_ENTRIES);
+ return CreateArrayIterator(this, ITERATOR_KIND_ENTRIES);
}
function ArrayValues() {
- return CreateArrayIterator(this, ARRAY_ITERATOR_KIND_VALUES);
+ return CreateArrayIterator(this, ITERATOR_KIND_VALUES);
}
function ArrayKeys() {
- return CreateArrayIterator(this, ARRAY_ITERATOR_KIND_KEYS);
+ return CreateArrayIterator(this, ITERATOR_KIND_KEYS);
}
function SetUpArrayIterator() {
diff --git a/src/array.js b/src/array.js
index e23ecf3..a233c63 100644
--- a/src/array.js
+++ b/src/array.js
@@ -463,16 +463,18 @@
var n = TO_UINT32(this.length);
var m = %_ArgumentsLength();
- if (m > 0 && ObjectIsSealed(this)) {
- throw MakeTypeError("array_functions_change_sealed",
- ["Array.prototype.push"]);
- }
if (%IsObserved(this))
return ObservedArrayPush.apply(this, arguments);
for (var i = 0; i < m; i++) {
- this[i+n] = %_Arguments(i);
+ // Use SetProperty rather than a direct keyed store to ensure that the store
+ // site doesn't become poisened with an elements transition KeyedStoreIC.
+ //
+ // TODO(danno): Using %SetProperty is a temporary workaround. The spec says
+ // that ToObject needs to be called for primitive values (and
+ // Runtime_SetProperty seem to ignore them).
+ %SetProperty(this, i+n, %_Arguments(i), 0, kStrictMode);
}
var new_length = n + m;
@@ -649,28 +651,12 @@
var num_arguments = %_ArgumentsLength();
var is_sealed = ObjectIsSealed(this);
- if (num_arguments > 0 && is_sealed) {
- throw MakeTypeError("array_functions_change_sealed",
- ["Array.prototype.unshift"]);
- }
-
if (%IsObserved(this))
return ObservedArrayUnshift.apply(this, arguments);
if (IS_ARRAY(this) && !is_sealed) {
SmartMove(this, 0, 0, len, num_arguments);
} else {
- if (num_arguments == 0 && ObjectIsFrozen(this)) {
- // In the zero argument case, values from the prototype come into the
- // object. This can't be allowed on frozen arrays.
- for (var i = 0; i < len; i++) {
- if (!this.hasOwnProperty(i) && !IS_UNDEFINED(this[i])) {
- throw MakeTypeError("array_functions_on_frozen",
- ["Array.prototype.shift"]);
- }
- }
- }
-
SimpleMove(this, 0, 0, len, num_arguments);
}
diff --git a/src/assembler.cc b/src/assembler.cc
index 772b6d6..6728ef4 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -1053,18 +1053,6 @@
}
-ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) {
- return
- ExternalReference(Redirect(isolate, FUNCTION_ADDR(Runtime::PerformGC)));
-}
-
-
-ExternalReference ExternalReference::out_of_memory_function(Isolate* isolate) {
- return
- ExternalReference(Redirect(isolate, FUNCTION_ADDR(Runtime::OutOfMemory)));
-}
-
-
ExternalReference ExternalReference::delete_handle_scope_extensions(
Isolate* isolate) {
return ExternalReference(Redirect(
diff --git a/src/assembler.h b/src/assembler.h
index 0349b06..2742032 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -107,6 +107,22 @@
};
+// Avoids emitting debug code during the lifetime of this scope object.
+class DontEmitDebugCodeScope BASE_EMBEDDED {
+ public:
+ explicit DontEmitDebugCodeScope(AssemblerBase* assembler)
+ : assembler_(assembler), old_value_(assembler->emit_debug_code()) {
+ assembler_->set_emit_debug_code(false);
+ }
+ ~DontEmitDebugCodeScope() {
+ assembler_->set_emit_debug_code(old_value_);
+ };
+ private:
+ AssemblerBase* assembler_;
+ bool old_value_;
+};
+
+
// Avoids using instructions that vary in size in unpredictable ways between the
// snapshot and the running VM.
class PredictableCodeSizeScope {
@@ -747,8 +763,6 @@
static ExternalReference store_buffer_overflow_function(
Isolate* isolate);
static ExternalReference flush_icache_function(Isolate* isolate);
- static ExternalReference perform_gc_function(Isolate* isolate);
- static ExternalReference out_of_memory_function(Isolate* isolate);
static ExternalReference delete_handle_scope_extensions(Isolate* isolate);
static ExternalReference get_date_field_function(Isolate* isolate);
diff --git a/src/ast.cc b/src/ast.cc
index b9e0b38..a1037f7 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -1179,7 +1179,7 @@
} else {
str = DoubleToCString(value_->Number(), buffer);
}
- return isolate_->factory()->NewStringFromAscii(CStrVector(str));
+ return isolate_->factory()->NewStringFromAsciiChecked(str);
}
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index ba08aad..6c6e6b3 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -207,8 +207,11 @@
ElementsKind elements_kind);
bool InstallNatives();
- Handle<JSFunction> InstallTypedArray(const char* name,
- ElementsKind elementsKind);
+ void InstallTypedArray(
+ const char* name,
+ ElementsKind elements_kind,
+ Handle<JSFunction>* fun,
+ Handle<Map>* external_map);
bool InstallExperimentalNatives();
void InstallBuiltinFunctionIds();
void InstallJSFunctionResultCaches();
@@ -355,14 +358,14 @@
Factory* factory = isolate->factory();
Handle<String> internalized_name = factory->InternalizeUtf8String(name);
Handle<Code> call_code = Handle<Code>(isolate->builtins()->builtin(call));
- Handle<JSFunction> function = prototype.is_null() ?
- factory->NewFunctionWithoutPrototype(internalized_name, call_code) :
- factory->NewFunctionWithPrototype(internalized_name,
- type,
- instance_size,
- prototype,
- call_code,
- install_initial_map);
+ Handle<JSFunction> function = prototype.is_null()
+ ? factory->NewFunction(internalized_name, call_code)
+ : factory->NewFunctionWithPrototype(internalized_name,
+ type,
+ instance_size,
+ prototype,
+ call_code,
+ install_initial_map);
PropertyAttributes attributes;
if (target->IsJSBuiltinsObject()) {
attributes =
@@ -458,8 +461,8 @@
Handle<String> object_name = factory->Object_string();
{ // --- O b j e c t ---
- Handle<JSFunction> object_fun =
- factory->NewFunction(object_name, factory->null_value());
+ Handle<JSFunction> object_fun = factory->NewFunctionWithPrototype(
+ object_name, factory->null_value());
Handle<Map> object_function_map =
factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
object_fun->set_initial_map(*object_function_map);
@@ -484,17 +487,11 @@
// 262 15.3.4.
Handle<String> empty_string =
factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("Empty"));
- Handle<JSFunction> empty_function =
- factory->NewFunctionWithoutPrototype(empty_string, SLOPPY);
+ Handle<Code> code(isolate->builtins()->builtin(Builtins::kEmptyFunction));
+ Handle<JSFunction> empty_function = factory->NewFunction(empty_string, code);
// --- E m p t y ---
- Handle<Code> code =
- Handle<Code>(isolate->builtins()->builtin(
- Builtins::kEmptyFunction));
- empty_function->set_code(*code);
- empty_function->shared()->set_code(*code);
- Handle<String> source =
- factory->NewStringFromOneByte(STATIC_ASCII_VECTOR("() {}"));
+ Handle<String> source = factory->NewStringFromStaticAscii("() {}");
Handle<Script> script = factory->NewScript(source);
script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
empty_function->shared()->set_script(*script);
@@ -567,16 +564,13 @@
if (throw_type_error_function.is_null()) {
Handle<String> name = factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("ThrowTypeError"));
- throw_type_error_function =
- factory()->NewFunctionWithoutPrototype(name, SLOPPY);
Handle<Code> code(isolate()->builtins()->builtin(
Builtins::kStrictModePoisonPill));
+ throw_type_error_function = factory()->NewFunction(name, code);
throw_type_error_function->set_map(native_context()->sloppy_function_map());
- throw_type_error_function->set_code(*code);
- throw_type_error_function->shared()->set_code(*code);
throw_type_error_function->shared()->DontAdaptArguments();
- JSObject::PreventExtensions(throw_type_error_function);
+ JSObject::PreventExtensions(throw_type_error_function).Assert();
}
return throw_type_error_function;
}
@@ -766,9 +760,10 @@
if (global_object.location() != NULL) {
ASSERT(global_object->IsJSGlobalProxy());
- return ReinitializeJSGlobalProxy(
- global_proxy_function,
- Handle<JSGlobalProxy>::cast(global_object));
+ Handle<JSGlobalProxy> global_proxy =
+ Handle<JSGlobalProxy>::cast(global_object);
+ factory()->ReinitializeJSGlobalProxy(global_proxy, global_proxy_function);
+ return global_proxy;
} else {
return Handle<JSGlobalProxy>::cast(
factory()->NewJSObject(global_proxy_function, TENURED));
@@ -910,10 +905,10 @@
Handle<Map>(native_context()->string_function()->initial_map());
Map::EnsureDescriptorSlack(string_map, 1);
- Handle<Foreign> string_length(
- factory->NewForeign(&Accessors::StringLength));
PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE | READ_ONLY);
+ Handle<AccessorInfo> string_length(
+ Accessors::StringLengthInfo(isolate, attribs));
{ // Add length.
CallbacksDescriptor d(factory->length_string(), string_length, attribs);
@@ -1022,8 +1017,8 @@
{ // -- J S O N
Handle<String> name = factory->InternalizeUtf8String("JSON");
- Handle<JSFunction> cons = factory->NewFunction(name,
- factory->the_hole_value());
+ Handle<JSFunction> cons = factory->NewFunctionWithPrototype(
+ name, factory->the_hole_value());
JSFunction::SetInstancePrototype(cons,
Handle<Object>(native_context()->initial_object_prototype(), isolate));
cons->SetInstanceClassName(*name);
@@ -1047,9 +1042,14 @@
{ // -- T y p e d A r r a y s
#define INSTALL_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
{ \
- Handle<JSFunction> fun = InstallTypedArray(#Type "Array", \
- TYPE##_ELEMENTS); \
+ Handle<JSFunction> fun; \
+ Handle<Map> external_map; \
+ InstallTypedArray(#Type "Array", \
+ TYPE##_ELEMENTS, \
+ &fun, \
+ &external_map); \
native_context()->set_##type##_array_fun(*fun); \
+ native_context()->set_##type##_array_external_map(*external_map); \
}
TYPED_ARRAYS(INSTALL_TYPED_ARRAY)
#undef INSTALL_TYPED_ARRAY
@@ -1069,11 +1069,9 @@
// class_name equals 'Arguments'.
Handle<String> arguments_string = factory->InternalizeOneByteString(
STATIC_ASCII_VECTOR("Arguments"));
- Handle<Code> code = Handle<Code>(
- isolate->builtins()->builtin(Builtins::kIllegal));
- Handle<JSObject> prototype =
- Handle<JSObject>(
- JSObject::cast(native_context()->object_function()->prototype()));
+ Handle<Code> code(isolate->builtins()->builtin(Builtins::kIllegal));
+ Handle<JSObject> prototype(
+ JSObject::cast(native_context()->object_function()->prototype()));
Handle<JSFunction> function =
factory->NewFunctionWithPrototype(arguments_string,
@@ -1262,18 +1260,26 @@
}
-Handle<JSFunction> Genesis::InstallTypedArray(
- const char* name, ElementsKind elementsKind) {
+void Genesis::InstallTypedArray(
+ const char* name,
+ ElementsKind elements_kind,
+ Handle<JSFunction>* fun,
+ Handle<Map>* external_map) {
Handle<JSObject> global = Handle<JSObject>(native_context()->global_object());
Handle<JSFunction> result = InstallFunction(global, name, JS_TYPED_ARRAY_TYPE,
JSTypedArray::kSize, isolate()->initial_object_prototype(),
Builtins::kIllegal, false, true);
Handle<Map> initial_map = isolate()->factory()->NewMap(
- JS_TYPED_ARRAY_TYPE, JSTypedArray::kSizeWithInternalFields, elementsKind);
+ JS_TYPED_ARRAY_TYPE,
+ JSTypedArray::kSizeWithInternalFields,
+ elements_kind);
result->set_initial_map(*initial_map);
initial_map->set_constructor(*result);
- return result;
+ *fun = result;
+
+ ElementsKind external_kind = GetNextTransitionElementsKind(elements_kind);
+ *external_map = Map::AsElementsKind(initial_map, external_kind);
}
@@ -1303,6 +1309,16 @@
isolate()->initial_object_prototype(),
Builtins::kIllegal, true, true);
}
+ { // -- S e t I t e r a t o r
+ Handle<Map> map = isolate()->factory()->NewMap(
+ JS_SET_ITERATOR_TYPE, JSSetIterator::kSize);
+ native_context()->set_set_iterator_map(*map);
+ }
+ { // -- M a p I t e r a t o r
+ Handle<Map> map = isolate()->factory()->NewMap(
+ JS_MAP_ITERATOR_TYPE, JSMapIterator::kSize);
+ native_context()->set_map_iterator_map(*map);
+ }
}
if (FLAG_harmony_weak_collections) {
@@ -1357,37 +1373,38 @@
*generator_object_prototype);
native_context()->set_generator_object_prototype_map(
*generator_object_prototype_map);
+ }
- // Create a map for generator result objects.
- ASSERT(object_function->initial_map()->inobject_properties() == 0);
+ if (FLAG_harmony_collections || FLAG_harmony_generators) {
+ // Collection forEach uses an iterator result object.
+ // Generators return iteraror result objects.
+
STATIC_ASSERT(JSGeneratorObject::kResultPropertyCount == 2);
- Handle<Map> generator_result_map = Map::Create(
+ Handle<JSFunction> object_function(native_context()->object_function());
+ ASSERT(object_function->initial_map()->inobject_properties() == 0);
+ Handle<Map> iterator_result_map = Map::Create(
object_function, JSGeneratorObject::kResultPropertyCount);
- ASSERT(generator_result_map->inobject_properties() ==
+ ASSERT(iterator_result_map->inobject_properties() ==
JSGeneratorObject::kResultPropertyCount);
Map::EnsureDescriptorSlack(
- generator_result_map, JSGeneratorObject::kResultPropertyCount);
+ iterator_result_map, JSGeneratorObject::kResultPropertyCount);
- Handle<String> value_string = factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("value"));
- FieldDescriptor value_descr(value_string,
+ FieldDescriptor value_descr(isolate()->factory()->value_string(),
JSGeneratorObject::kResultValuePropertyIndex,
NONE,
Representation::Tagged());
- generator_result_map->AppendDescriptor(&value_descr);
+ iterator_result_map->AppendDescriptor(&value_descr);
- Handle<String> done_string = factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("done"));
- FieldDescriptor done_descr(done_string,
+ FieldDescriptor done_descr(isolate()->factory()->done_string(),
JSGeneratorObject::kResultDonePropertyIndex,
NONE,
Representation::Tagged());
- generator_result_map->AppendDescriptor(&done_descr);
+ iterator_result_map->AppendDescriptor(&done_descr);
- generator_result_map->set_unused_property_fields(0);
+ iterator_result_map->set_unused_property_fields(0);
ASSERT_EQ(JSGeneratorObject::kResultSize,
- generator_result_map->instance_size());
- native_context()->set_generator_result_map(*generator_result_map);
+ iterator_result_map->instance_size());
+ native_context()->set_iterator_result_map(*iterator_result_map);
}
}
@@ -1403,10 +1420,12 @@
bool Genesis::CompileExperimentalBuiltin(Isolate* isolate, int index) {
Vector<const char> name = ExperimentalNatives::GetScriptName(index);
Factory* factory = isolate->factory();
- Handle<String> source_code =
+ Handle<String> source_code;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, source_code,
factory->NewStringFromAscii(
- ExperimentalNatives::GetRawScriptSource(index));
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, source_code, false);
+ ExperimentalNatives::GetRawScriptSource(index)),
+ false);
return CompileNative(isolate, name, source_code);
}
@@ -1455,8 +1474,8 @@
// function and insert it into the cache.
if (cache == NULL || !cache->Lookup(name, &function_info)) {
ASSERT(source->IsOneByteRepresentation());
- Handle<String> script_name = factory->NewStringFromUtf8(name);
- ASSERT(!script_name.is_null());
+ Handle<String> script_name =
+ factory->NewStringFromUtf8(name).ToHandleChecked();
function_info = Compiler::CompileScript(
source,
script_name,
@@ -1655,9 +1674,8 @@
set_builtins(*builtins);
// Create a bridge function that has context in the native context.
- Handle<JSFunction> bridge =
- factory()->NewFunction(factory()->empty_string(),
- factory()->undefined_value());
+ Handle<JSFunction> bridge = factory()->NewFunctionWithPrototype(
+ factory()->empty_string(), factory()->undefined_value());
ASSERT(bridge->context() == *isolate()->native_context());
// Allocate the builtins context.
@@ -1681,125 +1699,108 @@
Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
Map::EnsureDescriptorSlack(script_map, 13);
- Handle<Foreign> script_source(
- factory()->NewForeign(&Accessors::ScriptSource));
- Handle<Foreign> script_name(factory()->NewForeign(&Accessors::ScriptName));
- Handle<String> id_string(factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("id")));
- Handle<Foreign> script_id(factory()->NewForeign(&Accessors::ScriptId));
- Handle<String> line_offset_string(
- factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("line_offset")));
- Handle<Foreign> script_line_offset(
- factory()->NewForeign(&Accessors::ScriptLineOffset));
- Handle<String> column_offset_string(
- factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("column_offset")));
- Handle<Foreign> script_column_offset(
- factory()->NewForeign(&Accessors::ScriptColumnOffset));
- Handle<String> type_string(factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("type")));
- Handle<Foreign> script_type(factory()->NewForeign(&Accessors::ScriptType));
- Handle<String> compilation_type_string(
- factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("compilation_type")));
- Handle<Foreign> script_compilation_type(
- factory()->NewForeign(&Accessors::ScriptCompilationType));
- Handle<String> line_ends_string(factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("line_ends")));
- Handle<Foreign> script_line_ends(
- factory()->NewForeign(&Accessors::ScriptLineEnds));
- Handle<String> context_data_string(
- factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("context_data")));
- Handle<Foreign> script_context_data(
- factory()->NewForeign(&Accessors::ScriptContextData));
- Handle<String> eval_from_script_string(
- factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("eval_from_script")));
- Handle<Foreign> script_eval_from_script(
- factory()->NewForeign(&Accessors::ScriptEvalFromScript));
- Handle<String> eval_from_script_position_string(
- factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("eval_from_script_position")));
- Handle<Foreign> script_eval_from_script_position(
- factory()->NewForeign(&Accessors::ScriptEvalFromScriptPosition));
- Handle<String> eval_from_function_name_string(
- factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("eval_from_function_name")));
- Handle<Foreign> script_eval_from_function_name(
- factory()->NewForeign(&Accessors::ScriptEvalFromFunctionName));
PropertyAttributes attribs =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
+ Handle<AccessorInfo> script_column =
+ Accessors::ScriptColumnOffsetInfo(isolate(), attribs);
+ {
+ CallbacksDescriptor d(Handle<Name>(Name::cast(script_column->name())),
+ script_column, attribs);
+ script_map->AppendDescriptor(&d);
+ }
+
+ Handle<AccessorInfo> script_id =
+ Accessors::ScriptIdInfo(isolate(), attribs);
+ {
+ CallbacksDescriptor d(Handle<Name>(Name::cast(script_id->name())),
+ script_id, attribs);
+ script_map->AppendDescriptor(&d);
+ }
+
+
+ Handle<AccessorInfo> script_name =
+ Accessors::ScriptNameInfo(isolate(), attribs);
+ {
+ CallbacksDescriptor d(Handle<Name>(Name::cast(script_name->name())),
+ script_name, attribs);
+ script_map->AppendDescriptor(&d);
+ }
+
+ Handle<AccessorInfo> script_line =
+ Accessors::ScriptLineOffsetInfo(isolate(), attribs);
+ {
+ CallbacksDescriptor d(Handle<Name>(Name::cast(script_line->name())),
+ script_line, attribs);
+ script_map->AppendDescriptor(&d);
+ }
+
+ Handle<AccessorInfo> script_source =
+ Accessors::ScriptSourceInfo(isolate(), attribs);
+ {
+ CallbacksDescriptor d(Handle<Name>(Name::cast(script_source->name())),
+ script_source, attribs);
+ script_map->AppendDescriptor(&d);
+ }
+
+ Handle<AccessorInfo> script_type =
+ Accessors::ScriptTypeInfo(isolate(), attribs);
+ {
+ CallbacksDescriptor d(Handle<Name>(Name::cast(script_type->name())),
+ script_type, attribs);
+ script_map->AppendDescriptor(&d);
+ }
+
+ Handle<AccessorInfo> script_compilation_type =
+ Accessors::ScriptCompilationTypeInfo(isolate(), attribs);
{
CallbacksDescriptor d(
- factory()->source_string(), script_source, attribs);
+ Handle<Name>(Name::cast(script_compilation_type->name())),
+ script_compilation_type, attribs);
script_map->AppendDescriptor(&d);
}
+ Handle<AccessorInfo> script_line_ends =
+ Accessors::ScriptLineEndsInfo(isolate(), attribs);
{
- CallbacksDescriptor d(factory()->name_string(), script_name, attribs);
+ CallbacksDescriptor d(Handle<Name>(Name::cast(script_line_ends->name())),
+ script_line_ends, attribs);
script_map->AppendDescriptor(&d);
}
- {
- CallbacksDescriptor d(id_string, script_id, attribs);
- script_map->AppendDescriptor(&d);
- }
-
- {
- CallbacksDescriptor d(line_offset_string, script_line_offset, attribs);
- script_map->AppendDescriptor(&d);
- }
-
+ Handle<AccessorInfo> script_context_data =
+ Accessors::ScriptContextDataInfo(isolate(), attribs);
{
CallbacksDescriptor d(
- column_offset_string, script_column_offset, attribs);
+ Handle<Name>(Name::cast(script_context_data->name())),
+ script_context_data, attribs);
script_map->AppendDescriptor(&d);
}
- {
- CallbacksDescriptor d(type_string, script_type, attribs);
- script_map->AppendDescriptor(&d);
- }
-
+ Handle<AccessorInfo> script_eval_from_script =
+ Accessors::ScriptEvalFromScriptInfo(isolate(), attribs);
{
CallbacksDescriptor d(
- compilation_type_string, script_compilation_type, attribs);
+ Handle<Name>(Name::cast(script_eval_from_script->name())),
+ script_eval_from_script, attribs);
script_map->AppendDescriptor(&d);
}
- {
- CallbacksDescriptor d(line_ends_string, script_line_ends, attribs);
- script_map->AppendDescriptor(&d);
- }
-
+ Handle<AccessorInfo> script_eval_from_script_position =
+ Accessors::ScriptEvalFromScriptPositionInfo(isolate(), attribs);
{
CallbacksDescriptor d(
- context_data_string, script_context_data, attribs);
+ Handle<Name>(Name::cast(script_eval_from_script_position->name())),
+ script_eval_from_script_position, attribs);
script_map->AppendDescriptor(&d);
}
+ Handle<AccessorInfo> script_eval_from_function_name =
+ Accessors::ScriptEvalFromFunctionNameInfo(isolate(), attribs);
{
CallbacksDescriptor d(
- eval_from_script_string, script_eval_from_script, attribs);
- script_map->AppendDescriptor(&d);
- }
-
- {
- CallbacksDescriptor d(
- eval_from_script_position_string,
- script_eval_from_script_position,
- attribs);
- script_map->AppendDescriptor(&d);
- }
-
- {
- CallbacksDescriptor d(
- eval_from_function_name_string,
- script_eval_from_function_name,
- attribs);
+ Handle<Name>(Name::cast(script_eval_from_function_name->name())),
+ script_eval_from_function_name, attribs);
script_map->AppendDescriptor(&d);
}
@@ -2022,10 +2023,9 @@
static void InstallBuiltinFunctionId(Handle<JSObject> holder,
const char* function_name,
BuiltinFunctionId id) {
- Factory* factory = holder->GetIsolate()->factory();
- Handle<String> name = factory->InternalizeUtf8String(function_name);
+ Isolate* isolate = holder->GetIsolate();
Handle<Object> function_object =
- Object::GetProperty(holder, name).ToHandleChecked();
+ Object::GetProperty(isolate, holder, function_name).ToHandleChecked();
Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
function->shared()->set_function_data(Smi::FromInt(id));
}
@@ -2132,7 +2132,8 @@
false);
}
- Handle<Object> Error = GetProperty(global, "Error").ToHandleChecked();
+ Handle<Object> Error = Object::GetProperty(
+ isolate, global, "Error").ToHandleChecked();
if (Error->IsJSObject()) {
Handle<String> name = factory->InternalizeOneByteString(
STATIC_ASCII_VECTOR("stackTraceLimit"));
@@ -2178,12 +2179,7 @@
}
-static bool MatchRegisteredExtensions(void* key1, void* key2) {
- return key1 == key2;
-}
-
-Genesis::ExtensionStates::ExtensionStates()
- : map_(MatchRegisteredExtensions, 8) { }
+Genesis::ExtensionStates::ExtensionStates() : map_(HashMap::PointersMatch, 8) {}
Genesis::ExtensionTraversalState Genesis::ExtensionStates::get_state(
RegisteredExtension* extension) {
@@ -2318,10 +2314,8 @@
HandleScope scope(isolate());
for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) {
Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i);
- Handle<String> name =
- factory()->InternalizeUtf8String(Builtins::GetName(id));
- Handle<Object> function_object =
- Object::GetProperty(builtins, name).ToHandleChecked();
+ Handle<Object> function_object = Object::GetProperty(
+ isolate(), builtins, Builtins::GetName(id)).ToHandleChecked();
Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
builtins->set_javascript_builtin(id, *function);
if (!Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) {
diff --git a/src/bootstrapper.h b/src/bootstrapper.h
index 6dea116..f6fcd02 100644
--- a/src/bootstrapper.h
+++ b/src/bootstrapper.h
@@ -47,7 +47,8 @@
Handle<FixedArray> new_array = factory->NewFixedArray(length + 2, TENURED);
cache_->CopyTo(0, *new_array, 0, cache_->length());
cache_ = *new_array;
- Handle<String> str = factory->NewStringFromAscii(name, TENURED);
+ Handle<String> str =
+ factory->NewStringFromAscii(name, TENURED).ToHandleChecked();
ASSERT(!str.is_null());
cache_->set(length, *str);
cache_->set(length + 1, *shared);
diff --git a/src/builtins.cc b/src/builtins.cc
index 3f81086..f4ce991 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -127,28 +127,28 @@
#ifdef DEBUG
#define BUILTIN(name) \
- MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
+ MUST_USE_RESULT static Object* Builtin_Impl_##name( \
name##ArgumentsType args, Isolate* isolate); \
- MUST_USE_RESULT static MaybeObject* Builtin_##name( \
+ MUST_USE_RESULT static Object* Builtin_##name( \
int args_length, Object** args_object, Isolate* isolate) { \
name##ArgumentsType args(args_length, args_object); \
args.Verify(); \
return Builtin_Impl_##name(args, isolate); \
} \
- MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
+ MUST_USE_RESULT static Object* Builtin_Impl_##name( \
name##ArgumentsType args, Isolate* isolate)
#else // For release mode.
#define BUILTIN(name) \
- static MaybeObject* Builtin_impl##name( \
+ static Object* Builtin_impl##name( \
name##ArgumentsType args, Isolate* isolate); \
- static MaybeObject* Builtin_##name( \
+ static Object* Builtin_##name( \
int args_length, Object** args_object, Isolate* isolate) { \
name##ArgumentsType args(args_length, args_object); \
return Builtin_impl##name(args, isolate); \
} \
- static MaybeObject* Builtin_impl##name( \
+ static Object* Builtin_impl##name( \
name##ArgumentsType args, Isolate* isolate)
#endif
@@ -366,15 +366,16 @@
}
-MUST_USE_RESULT static MaybeObject* CallJsBuiltin(
+MUST_USE_RESULT static Object* CallJsBuiltin(
Isolate* isolate,
const char* name,
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
HandleScope handleScope(isolate);
- Handle<Object> js_builtin =
- GetProperty(Handle<JSObject>(isolate->native_context()->builtins()),
- name).ToHandleChecked();
+ Handle<Object> js_builtin = Object::GetProperty(
+ isolate,
+ handle(isolate->native_context()->builtins(), isolate),
+ name).ToHandleChecked();
Handle<JSFunction> function = Handle<JSFunction>::cast(js_builtin);
int argc = args.length() - 1;
ScopedVector<Handle<Object> > argv(argc);
@@ -528,7 +529,7 @@
}
Handle<Object> element;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element, maybe_element);
- RETURN_IF_EMPTY_HANDLE(
+ RETURN_FAILURE_ON_EXCEPTION(
isolate,
accessor->SetLength(array, handle(Smi::FromInt(new_length), isolate)));
return *element;
@@ -1165,7 +1166,7 @@
template <bool is_construct>
-MUST_USE_RESULT static MaybeObject* HandleApiCallHelper(
+MUST_USE_RESULT static Object* HandleApiCallHelper(
BuiltinArguments<NEEDS_CALLED_FUNCTION> args, Isolate* isolate) {
ASSERT(is_construct == CalledAsConstructor(isolate));
Heap* heap = isolate->heap();
@@ -1230,7 +1231,7 @@
result->VerifyApiCallResultType();
}
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
if (!is_construct || result->IsJSObject()) return result;
}
@@ -1251,7 +1252,7 @@
// Helper function to handle calls to non-function objects created through the
// API. The object can be called as either a constructor (using new) or just as
// a function (without new).
-MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor(
+MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
Isolate* isolate,
bool is_construct_call,
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
@@ -1300,7 +1301,7 @@
}
}
// Check for exceptions and return result.
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return result;
}
@@ -1622,7 +1623,6 @@
void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
ASSERT(!initialized_);
- Heap* heap = isolate->heap();
// Create a scope for the handles in the builtins.
HandleScope scope(isolate);
@@ -1653,32 +1653,18 @@
CodeDesc desc;
masm.GetCode(&desc);
Code::Flags flags = functions[i].flags;
- Object* code = NULL;
- {
- // During startup it's OK to always allocate and defer GC to later.
- // This simplifies things because we don't need to retry.
- AlwaysAllocateScope __scope__(isolate);
- { MaybeObject* maybe_code =
- heap->CreateCode(desc, flags, masm.CodeObject());
- if (!maybe_code->ToObject(&code)) {
- v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
- }
- }
- }
+ Handle<Code> code =
+ isolate->factory()->NewCode(desc, flags, masm.CodeObject());
// Log the event and add the code to the builtins array.
PROFILE(isolate,
- CodeCreateEvent(Logger::BUILTIN_TAG,
- Code::cast(code),
- functions[i].s_name));
- GDBJIT(AddCode(GDBJITInterface::BUILTIN,
- functions[i].s_name,
- Code::cast(code)));
- builtins_[i] = code;
+ CodeCreateEvent(Logger::BUILTIN_TAG, *code, functions[i].s_name));
+ GDBJIT(AddCode(GDBJITInterface::BUILTIN, functions[i].s_name, *code));
+ builtins_[i] = *code;
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_builtin_code) {
CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
PrintF(trace_scope.file(), "Builtin: %s\n", functions[i].s_name);
- Code::cast(code)->Disassemble(functions[i].s_name, trace_scope.file());
+ code->Disassemble(functions[i].s_name, trace_scope.file());
PrintF(trace_scope.file(), "\n");
}
#endif
diff --git a/src/builtins.h b/src/builtins.h
index 88cfd53..16d7835 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -260,7 +260,7 @@
V(STRING_ADD_LEFT, 1) \
V(STRING_ADD_RIGHT, 1) \
V(APPLY_PREPARE, 1) \
- V(APPLY_OVERFLOW, 1)
+ V(STACK_OVERFLOW, 1)
class BuiltinFunctionTable;
class ObjectVisitor;
diff --git a/src/checks.cc b/src/checks.cc
index 3a2de28..2583d08 100644
--- a/src/checks.cc
+++ b/src/checks.cc
@@ -98,8 +98,6 @@
// Contains protection against recursive calls (faults while handling faults).
extern "C" void V8_Fatal(const char* file, int line, const char* format, ...) {
- i::AllowHandleDereference allow_deref;
- i::AllowDeferredHandleDereference allow_deferred_deref;
fflush(stdout);
fflush(stderr);
i::OS::PrintError("\n\n#\n# Fatal error in %s, line %d\n# ", file, line);
diff --git a/src/code-stubs.h b/src/code-stubs.h
index ed08fcf..fd0c039 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -74,7 +74,6 @@
V(CEntry) \
V(JSEntry) \
V(KeyedLoadElement) \
- V(ArrayPush) \
V(ArrayNoArgumentConstructor) \
V(ArraySingleArgumentConstructor) \
V(ArrayNArgumentsConstructor) \
@@ -1165,30 +1164,6 @@
};
-class ArrayPushStub: public PlatformCodeStub {
- public:
- ArrayPushStub(ElementsKind kind, int argc) {
- bit_field_ = ElementsKindBits::encode(kind) | ArgcBits::encode(argc);
- }
-
- void Generate(MacroAssembler* masm);
-
- private:
- int arguments_count() { return ArgcBits::decode(bit_field_); }
- ElementsKind elements_kind() {
- return ElementsKindBits::decode(bit_field_);
- }
-
- virtual CodeStub::Major MajorKey() { return ArrayPush; }
- virtual int MinorKey() { return bit_field_; }
-
- class ElementsKindBits: public BitField<ElementsKind, 0, 3> {};
- class ArgcBits: public BitField<int, 3, Code::kArgumentsBits> {};
-
- int bit_field_;
-};
-
-
// TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
// call support for stubs in Hydrogen.
class BinaryOpICWithAllocationSiteStub V8_FINAL : public PlatformCodeStub {
@@ -1507,12 +1482,6 @@
};
private:
- void GenerateCore(MacroAssembler* masm,
- Label* throw_normal_exception,
- Label* throw_termination_exception,
- bool do_gc,
- bool always_allocate_scope);
-
// Number of pointers/values returned.
Isolate* isolate_;
const int result_size_;
diff --git a/src/collection.js b/src/collection.js
index 9054187..f2b481b 100644
--- a/src/collection.js
+++ b/src/collection.js
@@ -113,8 +113,29 @@
throw MakeTypeError('incompatible_method_receiver',
['Set.prototype.clear', this]);
}
- // Replace the internal table with a new empty table.
- %SetInitialize(this);
+ %SetClear(this);
+}
+
+
+function SetForEach(f, receiver) {
+ if (!IS_SET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Set.prototype.forEach', this]);
+ }
+
+ if (!IS_SPEC_FUNCTION(f)) {
+ throw MakeTypeError('called_non_callable', [f]);
+ }
+
+ var iterator = %SetCreateIterator(this, ITERATOR_KIND_VALUES);
+ var entry;
+ try {
+ while (!(entry = %SetIteratorNext(iterator)).done) {
+ %_CallFunction(receiver, entry.value, entry.value, this, f);
+ }
+ } finally {
+ %SetIteratorClose(iterator);
+ }
}
@@ -127,13 +148,16 @@
%FunctionSetPrototype($Set, new $Object());
%SetProperty($Set.prototype, "constructor", $Set, DONT_ENUM);
+ %FunctionSetLength(SetForEach, 1);
+
// Set up the non-enumerable functions on the Set prototype object.
InstallGetter($Set.prototype, "size", SetGetSize);
InstallFunctions($Set.prototype, DONT_ENUM, $Array(
"add", SetAdd,
"has", SetHas,
"delete", SetDelete,
- "clear", SetClear
+ "clear", SetClear,
+ "forEach", SetForEach
));
}
@@ -202,8 +226,29 @@
throw MakeTypeError('incompatible_method_receiver',
['Map.prototype.clear', this]);
}
- // Replace the internal table with a new empty table.
- %MapInitialize(this);
+ %MapClear(this);
+}
+
+
+function MapForEach(f, receiver) {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.forEach', this]);
+ }
+
+ if (!IS_SPEC_FUNCTION(f)) {
+ throw MakeTypeError('called_non_callable', [f]);
+ }
+
+ var iterator = %MapCreateIterator(this, ITERATOR_KIND_ENTRIES);
+ var entry;
+ try {
+ while (!(entry = %MapIteratorNext(iterator)).done) {
+ %_CallFunction(receiver, entry.value[1], entry.value[0], this, f);
+ }
+ } finally {
+ %MapIteratorClose(iterator);
+ }
}
@@ -216,6 +261,8 @@
%FunctionSetPrototype($Map, new $Object());
%SetProperty($Map.prototype, "constructor", $Map, DONT_ENUM);
+ %FunctionSetLength(MapForEach, 1);
+
// Set up the non-enumerable functions on the Map prototype object.
InstallGetter($Map.prototype, "size", MapGetSize);
InstallFunctions($Map.prototype, DONT_ENUM, $Array(
@@ -223,7 +270,8 @@
"set", MapSet,
"has", MapHas,
"delete", MapDelete,
- "clear", MapClear
+ "clear", MapClear,
+ "forEach", MapForEach
));
}
diff --git a/src/compiler.cc b/src/compiler.cc
index 1234639..86e8f2f 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -637,13 +637,14 @@
}
-static Handle<Code> GetUnoptimizedCodeCommon(CompilationInfo* info) {
+MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon(
+ CompilationInfo* info) {
VMState<COMPILER> state(info->isolate());
PostponeInterruptsScope postpone(info->isolate());
- if (!Parser::Parse(info)) return Handle<Code>::null();
+ if (!Parser::Parse(info)) return MaybeHandle<Code>();
info->SetStrictMode(info->function()->strict_mode());
- if (!CompileUnoptimizedCode(info)) return Handle<Code>::null();
+ if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>();
Compiler::RecordFunctionCompilation(
Logger::LAZY_COMPILE_TAG, info, info->shared_info());
UpdateSharedFunctionInfo(info);
@@ -652,7 +653,7 @@
}
-Handle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) {
+MaybeHandle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) {
ASSERT(!function->GetIsolate()->has_pending_exception());
ASSERT(!function->is_compiled());
if (function->shared()->is_compiled()) {
@@ -660,39 +661,43 @@
}
CompilationInfoWithZone info(function);
- Handle<Code> result = GetUnoptimizedCodeCommon(&info);
- ASSERT_EQ(result.is_null(), info.isolate()->has_pending_exception());
+ Handle<Code> result;
+ ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result,
+ GetUnoptimizedCodeCommon(&info),
+ Code);
if (FLAG_always_opt &&
- !result.is_null() &&
info.isolate()->use_crankshaft() &&
!info.shared_info()->optimization_disabled() &&
!info.isolate()->DebuggerHasBreakPoints()) {
- Handle<Code> opt_code = Compiler::GetOptimizedCode(
- function, result, Compiler::NOT_CONCURRENT);
- if (!opt_code.is_null()) result = opt_code;
+ Handle<Code> opt_code;
+ if (Compiler::GetOptimizedCode(
+ function, result,
+ Compiler::NOT_CONCURRENT).ToHandle(&opt_code)) {
+ result = opt_code;
+ }
}
return result;
}
-Handle<Code> Compiler::GetUnoptimizedCode(Handle<SharedFunctionInfo> shared) {
+MaybeHandle<Code> Compiler::GetUnoptimizedCode(
+ Handle<SharedFunctionInfo> shared) {
ASSERT(!shared->GetIsolate()->has_pending_exception());
ASSERT(!shared->is_compiled());
CompilationInfoWithZone info(shared);
- Handle<Code> result = GetUnoptimizedCodeCommon(&info);
- ASSERT_EQ(result.is_null(), info.isolate()->has_pending_exception());
- return result;
+ return GetUnoptimizedCodeCommon(&info);
}
bool Compiler::EnsureCompiled(Handle<JSFunction> function,
ClearExceptionFlag flag) {
if (function->is_compiled()) return true;
- Handle<Code> code = Compiler::GetUnoptimizedCode(function);
- if (code.is_null()) {
+ MaybeHandle<Code> maybe_code = Compiler::GetUnoptimizedCode(function);
+ Handle<Code> code;
+ if (!maybe_code.ToHandle(&code)) {
if (flag == CLEAR_EXCEPTION) {
function->GetIsolate()->clear_pending_exception();
}
@@ -713,7 +718,7 @@
// full code without debug break slots to full code with debug break slots
// depends on the generated code is otherwise exactly the same.
// If compilation fails, just keep the existing code.
-Handle<Code> Compiler::GetCodeForDebugging(Handle<JSFunction> function) {
+MaybeHandle<Code> Compiler::GetCodeForDebugging(Handle<JSFunction> function) {
CompilationInfoWithZone info(function);
Isolate* isolate = info.isolate();
VMState<COMPILER> state(isolate);
@@ -729,14 +734,15 @@
} else {
info.MarkNonOptimizable();
}
- Handle<Code> new_code = GetUnoptimizedCodeCommon(&info);
- if (new_code.is_null()) {
+ MaybeHandle<Code> maybe_new_code = GetUnoptimizedCodeCommon(&info);
+ Handle<Code> new_code;
+ if (!maybe_new_code.ToHandle(&new_code)) {
isolate->clear_pending_exception();
} else {
ASSERT_EQ(old_code->is_compiled_optimizable(),
new_code->is_compiled_optimizable());
}
- return new_code;
+ return maybe_new_code;
}
@@ -866,11 +872,12 @@
}
-Handle<JSFunction> Compiler::GetFunctionFromEval(Handle<String> source,
- Handle<Context> context,
- StrictMode strict_mode,
- ParseRestriction restriction,
- int scope_position) {
+MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
+ Handle<String> source,
+ Handle<Context> context,
+ StrictMode strict_mode,
+ ParseRestriction restriction,
+ int scope_position) {
Isolate* isolate = source->GetIsolate();
int source_length = source->length();
isolate->counters()->total_eval_size()->Increment(source_length);
@@ -898,7 +905,7 @@
shared_info = CompileToplevel(&info);
if (shared_info.is_null()) {
- return Handle<JSFunction>::null();
+ return MaybeHandle<JSFunction>();
} else {
// Explicitly disable optimization for eval code. We're not yet prepared
// to handle eval-code in the optimizing compiler.
@@ -1047,8 +1054,9 @@
}
-static Handle<Code> GetCodeFromOptimizedCodeMap(Handle<JSFunction> function,
- BailoutId osr_ast_id) {
+MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
+ Handle<JSFunction> function,
+ BailoutId osr_ast_id) {
if (FLAG_cache_optimized_code) {
Handle<SharedFunctionInfo> shared(function->shared());
DisallowHeapAllocation no_gc;
@@ -1068,7 +1076,7 @@
return Handle<Code>(shared->GetCodeFromOptimizedCodeMap(index));
}
}
- return Handle<Code>::null();
+ return MaybeHandle<Code>();
}
@@ -1155,12 +1163,15 @@
}
-Handle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
- Handle<Code> current_code,
- ConcurrencyMode mode,
- BailoutId osr_ast_id) {
- Handle<Code> cached_code = GetCodeFromOptimizedCodeMap(function, osr_ast_id);
- if (!cached_code.is_null()) return cached_code;
+MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
+ Handle<Code> current_code,
+ ConcurrencyMode mode,
+ BailoutId osr_ast_id) {
+ Handle<Code> cached_code;
+ if (GetCodeFromOptimizedCodeMap(
+ function, osr_ast_id).ToHandle(&cached_code)) {
+ return cached_code;
+ }
SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(function));
Isolate* isolate = info->isolate();
@@ -1193,7 +1204,7 @@
}
if (isolate->has_pending_exception()) isolate->clear_pending_exception();
- return Handle<Code>::null();
+ return MaybeHandle<Code>();
}
@@ -1257,12 +1268,13 @@
info->isolate()->cpu_profiler()->is_profiling()) {
Handle<Script> script = info->script();
Handle<Code> code = info->code();
- if (code.is_identical_to(info->isolate()->builtins()->CompileUnoptimized()))
+ if (code.is_identical_to(
+ info->isolate()->builtins()->CompileUnoptimized())) {
return;
- int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
+ }
+ int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
int column_num =
- GetScriptColumnNumber(script, shared->start_position()) + 1;
- USE(line_num);
+ Script::GetColumnNumber(script, shared->start_position()) + 1;
String* script_name = script->name()->IsString()
? String::cast(script->name())
: info->isolate()->heap()->empty_string();
diff --git a/src/compiler.h b/src/compiler.h
index 4bdb7ae..ca49c79 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -615,22 +615,26 @@
class Compiler : public AllStatic {
public:
- static Handle<Code> GetUnoptimizedCode(Handle<JSFunction> function);
- static Handle<Code> GetUnoptimizedCode(Handle<SharedFunctionInfo> shared);
+ MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode(
+ Handle<JSFunction> function);
+ MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode(
+ Handle<SharedFunctionInfo> shared);
static bool EnsureCompiled(Handle<JSFunction> function,
ClearExceptionFlag flag);
- static Handle<Code> GetCodeForDebugging(Handle<JSFunction> function);
+ MUST_USE_RESULT static MaybeHandle<Code> GetCodeForDebugging(
+ Handle<JSFunction> function);
#ifdef ENABLE_DEBUGGER_SUPPORT
static void CompileForLiveEdit(Handle<Script> script);
#endif
// Compile a String source within a context for eval.
- static Handle<JSFunction> GetFunctionFromEval(Handle<String> source,
- Handle<Context> context,
- StrictMode strict_mode,
- ParseRestriction restriction,
- int scope_position);
+ MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
+ Handle<String> source,
+ Handle<Context> context,
+ StrictMode strict_mode,
+ ParseRestriction restriction,
+ int scope_position);
// Compile a String source within a context.
static Handle<SharedFunctionInfo> CompileScript(
@@ -654,7 +658,7 @@
// Generate and return optimized code or start a concurrent optimization job.
// In the latter case, return the InOptimizationQueue builtin. On failure,
// return the empty handle.
- static Handle<Code> GetOptimizedCode(
+ MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode(
Handle<JSFunction> function,
Handle<Code> current_code,
ConcurrencyMode mode,
diff --git a/src/contexts.cc b/src/contexts.cc
index 5ee0d4b..d6866d0 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -365,11 +365,11 @@
Handle<Object> Context::ErrorMessageForCodeGenerationFromStrings() {
- Handle<Object> result(error_message_for_code_gen_from_strings(),
- GetIsolate());
+ Isolate* isolate = GetIsolate();
+ Handle<Object> result(error_message_for_code_gen_from_strings(), isolate);
if (!result->IsUndefined()) return result;
- return GetIsolate()->factory()->NewStringFromOneByte(STATIC_ASCII_VECTOR(
- "Code generation from strings disallowed for this context"));
+ return isolate->factory()->NewStringFromStaticAscii(
+ "Code generation from strings disallowed for this context");
}
diff --git a/src/contexts.h b/src/contexts.h
index 6ba9b3e..9cd9ffa 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -134,6 +134,16 @@
V(FLOAT32_ARRAY_FUN_INDEX, JSFunction, float32_array_fun) \
V(FLOAT64_ARRAY_FUN_INDEX, JSFunction, float64_array_fun) \
V(UINT8_CLAMPED_ARRAY_FUN_INDEX, JSFunction, uint8_clamped_array_fun) \
+ V(INT8_ARRAY_EXTERNAL_MAP_INDEX, Map, int8_array_external_map) \
+ V(UINT8_ARRAY_EXTERNAL_MAP_INDEX, Map, uint8_array_external_map) \
+ V(INT16_ARRAY_EXTERNAL_MAP_INDEX, Map, int16_array_external_map) \
+ V(UINT16_ARRAY_EXTERNAL_MAP_INDEX, Map, uint16_array_external_map) \
+ V(INT32_ARRAY_EXTERNAL_MAP_INDEX, Map, int32_array_external_map) \
+ V(UINT32_ARRAY_EXTERNAL_MAP_INDEX, Map, uint32_array_external_map) \
+ V(FLOAT32_ARRAY_EXTERNAL_MAP_INDEX, Map, float32_array_external_map) \
+ V(FLOAT64_ARRAY_EXTERNAL_MAP_INDEX, Map, float64_array_external_map) \
+ V(UINT8_CLAMPED_ARRAY_EXTERNAL_MAP_INDEX, Map, \
+ uint8_clamped_array_external_map) \
V(DATA_VIEW_FUN_INDEX, JSFunction, data_view_fun) \
V(SLOPPY_FUNCTION_MAP_INDEX, Map, sloppy_function_map) \
V(STRICT_FUNCTION_MAP_INDEX, Map, strict_function_map) \
@@ -191,7 +201,9 @@
V(STRICT_GENERATOR_FUNCTION_MAP_INDEX, Map, strict_generator_function_map) \
V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, \
generator_object_prototype_map) \
- V(GENERATOR_RESULT_MAP_INDEX, Map, generator_result_map)
+ V(ITERATOR_RESULT_MAP_INDEX, Map, iterator_result_map) \
+ V(MAP_ITERATOR_MAP_INDEX, Map, map_iterator_map) \
+ V(SET_ITERATOR_MAP_INDEX, Map, set_iterator_map)
// JSFunctions are pairs (context, function code), sometimes also called
// closures. A Context object is used to represent function contexts and
@@ -309,6 +321,15 @@
FLOAT32_ARRAY_FUN_INDEX,
FLOAT64_ARRAY_FUN_INDEX,
UINT8_CLAMPED_ARRAY_FUN_INDEX,
+ INT8_ARRAY_EXTERNAL_MAP_INDEX,
+ UINT8_ARRAY_EXTERNAL_MAP_INDEX,
+ INT16_ARRAY_EXTERNAL_MAP_INDEX,
+ UINT16_ARRAY_EXTERNAL_MAP_INDEX,
+ INT32_ARRAY_EXTERNAL_MAP_INDEX,
+ UINT32_ARRAY_EXTERNAL_MAP_INDEX,
+ FLOAT32_ARRAY_EXTERNAL_MAP_INDEX,
+ FLOAT64_ARRAY_EXTERNAL_MAP_INDEX,
+ UINT8_CLAMPED_ARRAY_EXTERNAL_MAP_INDEX,
DATA_VIEW_FUN_INDEX,
MESSAGE_LISTENERS_INDEX,
MAKE_MESSAGE_FUN_INDEX,
@@ -347,7 +368,9 @@
SLOPPY_GENERATOR_FUNCTION_MAP_INDEX,
STRICT_GENERATOR_FUNCTION_MAP_INDEX,
GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX,
- GENERATOR_RESULT_MAP_INDEX,
+ ITERATOR_RESULT_MAP_INDEX,
+ MAP_ITERATOR_MAP_INDEX,
+ SET_ITERATOR_MAP_INDEX,
// Properties from here are treated as weak references by the full GC.
// Scavenge treats them as strong references.
diff --git a/src/conversions-inl.h b/src/conversions-inl.h
index e503eb5..af9576a 100644
--- a/src/conversions-inl.h
+++ b/src/conversions-inl.h
@@ -75,7 +75,11 @@
if (x < k2Pow52) {
x += k2Pow52;
uint32_t result;
+#ifndef V8_TARGET_BIG_ENDIAN
Address mantissa_ptr = reinterpret_cast<Address>(&x);
+#else
+ Address mantissa_ptr = reinterpret_cast<Address>(&x) + kIntSize;
+#endif
// Copy least significant 32 bits of mantissa.
OS::MemCopy(&result, mantissa_ptr, sizeof(result));
return negative ? ~result + 1 : result;
diff --git a/src/d8.cc b/src/d8.cc
index 4e14cd5..99be861 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -982,7 +982,7 @@
factory->NewFixedArray(js_args.argc);
for (int j = 0; j < js_args.argc; j++) {
i::Handle<i::String> arg =
- factory->NewStringFromUtf8(i::CStrVector(js_args[j]));
+ factory->NewStringFromUtf8(i::CStrVector(js_args[j])).ToHandleChecked();
arguments_array->set(j, *arg);
}
i::Handle<i::JSArray> arguments_jsarray =
diff --git a/src/debug-agent.cc b/src/debug-agent.cc
index 49790ce..3410d6f 100644
--- a/src/debug-agent.cc
+++ b/src/debug-agent.cc
@@ -229,10 +229,10 @@
decoder.WriteUtf16(temp.start(), utf16_length);
// Send the request received to the debugger.
- v8::Debug::SendCommand(temp.start(),
+ v8::Debug::SendCommand(reinterpret_cast<v8::Isolate*>(agent_->isolate()),
+ temp.start(),
utf16_length,
- NULL,
- reinterpret_cast<v8::Isolate*>(agent_->isolate()));
+ NULL);
if (is_closing_session) {
// Session is closed.
diff --git a/src/debug.cc b/src/debug.cc
index 41c608a..b41375b 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -753,8 +753,8 @@
Handle<String> source_code =
isolate->bootstrapper()->NativesSourceLookup(index);
Vector<const char> name = Natives::GetScriptName(index);
- Handle<String> script_name = factory->NewStringFromAscii(name);
- ASSERT(!script_name.is_null());
+ Handle<String> script_name =
+ factory->NewStringFromAscii(name).ToHandleChecked();
Handle<Context> context = isolate->native_context();
// Compile the script.
@@ -1061,7 +1061,7 @@
}
-RUNTIME_FUNCTION(Object*, Debug_Break) {
+RUNTIME_FUNCTION(Debug_Break) {
return isolate->debug()->Break(args);
}
@@ -1127,13 +1127,12 @@
// Call HandleBreakPointx.
Handle<Object> argv[] = { break_id, break_point_object };
Handle<Object> result;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, result,
- Execution::TryCall(check_break_point,
- isolate_->js_builtins_object(),
- ARRAY_SIZE(argv),
- argv),
- false);
+ if (!Execution::TryCall(check_break_point,
+ isolate_->js_builtins_object(),
+ ARRAY_SIZE(argv),
+ argv).ToHandle(&result)) {
+ return false;
+ }
// Return whether the break point is triggered.
return result->IsTrue();
@@ -2107,7 +2106,8 @@
bool prev_force_debugger_active =
isolate_->debugger()->force_debugger_active();
isolate_->debugger()->set_force_debugger_active(true);
- Handle<Code> code = Compiler::GetCodeForDebugging(function);
+ Handle<Code> code = Compiler::GetCodeForDebugging(
+ function).ToHandleChecked();
function->ReplaceCode(*code);
isolate_->debugger()->set_force_debugger_active(
prev_force_debugger_active);
@@ -2223,10 +2223,10 @@
// will compile all inner functions that cannot be compiled without a
// context, because Compiler::BuildFunctionInfo checks whether the
// debugger is active.
- Handle<Code> result = target_function.is_null()
+ MaybeHandle<Code> maybe_result = target_function.is_null()
? Compiler::GetUnoptimizedCode(target)
: Compiler::GetUnoptimizedCode(target_function);
- if (result.is_null()) return isolate_->heap()->undefined_value();
+ if (maybe_result.is_null()) return isolate_->heap()->undefined_value();
}
} // End while loop.
@@ -2620,8 +2620,7 @@
MaybeHandle<Object> Debugger::MakeBreakEvent(Handle<Object> break_points_hit) {
Handle<Object> exec_state;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate_, exec_state, MakeExecutionState(), Object);
+ if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
// Create the new break event object.
Handle<Object> argv[] = { exec_state, break_points_hit };
return MakeJSObject(CStrVector("MakeBreakEvent"), ARRAY_SIZE(argv), argv);
@@ -2631,8 +2630,7 @@
MaybeHandle<Object> Debugger::MakeExceptionEvent(Handle<Object> exception,
bool uncaught) {
Handle<Object> exec_state;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate_, exec_state, MakeExecutionState(), Object);
+ if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
// Create the new exception event object.
Handle<Object> argv[] = { exec_state,
exception,
@@ -2643,24 +2641,21 @@
MaybeHandle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
bool before) {
- Factory* factory = isolate_->factory();
- // Create the compile event object.
Handle<Object> exec_state;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate_, exec_state, MakeExecutionState(), Object);
- Handle<Object> script_wrapper = GetScriptWrapper(script);
+ if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
+ // Create the compile event object.
+ Handle<Object> script_wrapper = Script::GetWrapper(script);
Handle<Object> argv[] = { exec_state,
script_wrapper,
- factory->ToBoolean(before) };
+ isolate_->factory()->ToBoolean(before) };
return MakeJSObject(CStrVector("MakeCompileEvent"), ARRAY_SIZE(argv), argv);
}
MaybeHandle<Object> Debugger::MakeScriptCollectedEvent(int id) {
- // Create the script collected event object.
Handle<Object> exec_state;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate_, exec_state, MakeExecutionState(), Object);
+ if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
+ // Create the script collected event object.
Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_);
Handle<Object> argv[] = { exec_state, id_object };
@@ -2696,9 +2691,7 @@
// Create the event data object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, event_data, MakeExceptionEvent(exception, uncaught),
- /* void */ ;);
+ if (!MakeExceptionEvent(exception, uncaught).ToHandle(&event_data)) return;
// Process debug event.
ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
@@ -2722,8 +2715,7 @@
// Create the event data object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, event_data, MakeBreakEvent(break_points_hit), /* void */ ;);
+ if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
// Process debug event.
ProcessDebugEvent(v8::Break,
@@ -2747,8 +2739,7 @@
// Create the event data object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, event_data, MakeCompileEvent(script, true), /* void */ ;);
+ if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return;
// Process debug event.
ProcessDebugEvent(v8::BeforeCompile,
@@ -2797,7 +2788,7 @@
// Wrap the script object in a proper JS object before passing it
// to JavaScript.
- Handle<JSValue> wrapper = GetScriptWrapper(script);
+ Handle<Object> wrapper = Script::GetWrapper(script);
// Call UpdateScriptBreakPoints expect no exceptions.
Handle<Object> argv[] = { wrapper };
@@ -2814,8 +2805,7 @@
// Create the compile state object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, event_data, MakeCompileEvent(script, false), /* void */ ;);
+ if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return;
// Process debug event.
ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
@@ -2837,8 +2827,7 @@
// Create the script collected state object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, event_data, MakeScriptCollectedEvent(id), /* void */ ;);
+ if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return;
// Process debug event.
ProcessDebugEvent(v8::ScriptCollected,
@@ -2860,8 +2849,8 @@
// Create the execution state.
Handle<Object> exec_state;
// Bail out and don't call debugger if exception.
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, exec_state, MakeExecutionState(), /* void */ ;);
+ if (!MakeExecutionState().ToHandle(&exec_state)) return;
+
// First notify the message handler if any.
if (message_handler_ != NULL) {
NotifyMessageHandler(event,
@@ -3302,10 +3291,9 @@
// Create the execution state.
Handle<Object> exec_state;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, exec_state,
- MakeExecutionState(),
- isolate_->factory()->undefined_value());
+ if (!MakeExecutionState().ToHandle(&exec_state)) {
+ return isolate_->factory()->undefined_value();
+ }
Handle<Object> argv[] = { exec_state, data };
return Execution::Call(
@@ -3333,7 +3321,7 @@
// Once become suspended, V8 will stay so indefinitely long, until remote
// debugger connects and issues "continue" command.
Debugger::message_handler_ = StubMessageHandler2;
- v8::Debug::DebugBreak();
+ v8::Debug::DebugBreak(reinterpret_cast<v8::Isolate*>(isolate_));
}
if (agent_ == NULL) {
@@ -3538,8 +3526,8 @@
if (IsEvent()) {
// Call toJSONProtocol on the debug event object.
- Handle<Object> fun =
- GetProperty(event_data_, "toJSONProtocol").ToHandleChecked();
+ Handle<Object> fun = Object::GetProperty(
+ isolate, event_data_, "toJSONProtocol").ToHandleChecked();
if (!fun->IsJSFunction()) {
return v8::Handle<v8::String>();
}
diff --git a/src/debug.h b/src/debug.h
index 8a793a7..b0a6892 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -175,7 +175,9 @@
class ScriptCache : private HashMap {
public:
explicit ScriptCache(Isolate* isolate)
- : HashMap(ScriptMatch), isolate_(isolate), collected_scripts_(10) {}
+ : HashMap(HashMap::PointersMatch),
+ isolate_(isolate),
+ collected_scripts_(10) {}
virtual ~ScriptCache() { Clear(); }
// Add script to the cache.
@@ -193,9 +195,6 @@
return ComputeIntegerHash(key, v8::internal::kZeroHashSeed);
}
- // Scripts match if their keys (script id) match.
- static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; }
-
// Clear the cache releasing all the weak handles.
void Clear();
@@ -638,7 +637,7 @@
};
-DECLARE_RUNTIME_FUNCTION(Object*, Debug_Break);
+DECLARE_RUNTIME_FUNCTION(Debug_Break);
// Message delivered to the message handler callback. This is either a debugger
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 4d5e605..e2fa5f3 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -1840,7 +1840,7 @@
// We also need to make sure that the representation of all fields
// in the given object are general enough to hold a tagged value.
Handle<Map> map = Map::GeneralizeAllFieldRepresentations(
- Handle<Map>::cast(MaterializeNextValue()), Representation::Tagged());
+ Handle<Map>::cast(MaterializeNextValue()));
switch (map->instance_type()) {
case HEAP_NUMBER_TYPE: {
// Reuse the HeapNumber value directly as it is already properly
@@ -3341,7 +3341,7 @@
Handle<Object> map_object = slot_refs_[current_slot_].GetValue(isolate);
Handle<Map> map = Map::GeneralizeAllFieldRepresentations(
- Handle<Map>::cast(map_object), Representation::Tagged());
+ Handle<Map>::cast(map_object));
current_slot_++;
// TODO(jarin) this should be unified with the code in
// Deoptimizer::MaterializeNextHeapObject()
diff --git a/src/elements.cc b/src/elements.cc
index bbcf50f..9f83122 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -591,19 +591,17 @@
return ElementsTraits::Kind;
}
- static void ValidateContents(JSObject* holder, int length) {
+ static void ValidateContents(Handle<JSObject> holder, int length) {
}
- static void ValidateImpl(JSObject* holder) {
- FixedArrayBase* fixed_array_base = holder->elements();
- // When objects are first allocated, its elements are Failures.
- if (fixed_array_base->IsFailure()) return;
+ static void ValidateImpl(Handle<JSObject> holder) {
+ Handle<FixedArrayBase> fixed_array_base(holder->elements());
if (!fixed_array_base->IsHeapObject()) return;
// Arrays that have been shifted in place can't be verified.
if (fixed_array_base->IsFiller()) return;
int length = 0;
if (holder->IsJSArray()) {
- Object* length_obj = JSArray::cast(holder)->length();
+ Object* length_obj = Handle<JSArray>::cast(holder)->length();
if (length_obj->IsSmi()) {
length = Smi::cast(length_obj)->value();
}
@@ -615,7 +613,7 @@
virtual void Validate(Handle<JSObject> holder) V8_FINAL V8_OVERRIDE {
DisallowHeapAllocation no_gc;
- ElementsAccessorSubclass::ValidateImpl(*holder);
+ ElementsAccessorSubclass::ValidateImpl(holder);
}
static bool HasElementImpl(Handle<Object> receiver,
@@ -1063,21 +1061,24 @@
return !Handle<BackingStore>::cast(backing_store)->is_the_hole(key);
}
- static void ValidateContents(JSObject* holder, int length) {
+ static void ValidateContents(Handle<JSObject> holder, int length) {
#if DEBUG
- FixedArrayBase* elements = holder->elements();
- Heap* heap = elements->GetHeap();
+ Isolate* isolate = holder->GetIsolate();
+ HandleScope scope(isolate);
+ Handle<FixedArrayBase> elements(holder->elements(), isolate);
Map* map = elements->map();
ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) &&
- (map == heap->fixed_array_map() ||
- map == heap->fixed_cow_array_map())) ||
+ (map == isolate->heap()->fixed_array_map() ||
+ map == isolate->heap()->fixed_cow_array_map())) ||
(IsFastDoubleElementsKind(KindTraits::Kind) ==
- ((map == heap->fixed_array_map() && length == 0) ||
- map == heap->fixed_double_array_map())));
+ ((map == isolate->heap()->fixed_array_map() && length == 0) ||
+ map == isolate->heap()->fixed_double_array_map())));
+ DisallowHeapAllocation no_gc;
for (int i = 0; i < length; i++) {
- BackingStore* backing_store = BackingStore::cast(elements);
+ HandleScope scope(isolate);
+ Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements);
ASSERT((!IsFastSmiElementsKind(KindTraits::Kind) ||
- static_cast<Object*>(backing_store->get(i))->IsSmi()) ||
+ BackingStore::get(backing_store, i)->IsSmi()) ||
(IsFastHoleyElementsKind(KindTraits::Kind) ==
backing_store->is_the_hole(i)));
}
diff --git a/src/execution.cc b/src/execution.cc
index 2e6023b..d52d471 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -54,7 +54,7 @@
}
// Placeholder for return value.
- MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
+ Object* value = NULL;
typedef Object* (*JSEntryFunction)(byte* entry,
Object* function,
@@ -740,13 +740,12 @@
Handle<Object> index_object = factory->NewNumberFromInt(int_index);
Handle<Object> index_arg[] = { index_object };
Handle<Object> result;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate, result,
- TryCall(Handle<JSFunction>::cast(char_at),
- string,
- ARRAY_SIZE(index_arg),
- index_arg),
- factory->undefined_value());
+ if (!TryCall(Handle<JSFunction>::cast(char_at),
+ string,
+ ARRAY_SIZE(index_arg),
+ index_arg).ToHandle(&result)) {
+ return factory->undefined_value();
+ }
return result;
}
@@ -942,7 +941,7 @@
}
#endif
-MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
+Object* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
StackGuard* stack_guard = isolate->stack_guard();
if (stack_guard->ShouldPostponeInterrupts()) {
return isolate->heap()->undefined_value();
diff --git a/src/execution.h b/src/execution.h
index 4510fd1..d483851 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -125,8 +125,7 @@
// If the stack guard is triggered, but it is not an actual
// stack overflow, then handle the interruption accordingly.
- MUST_USE_RESULT static MaybeObject* HandleStackGuardInterrupt(
- Isolate* isolate);
+ static Object* HandleStackGuardInterrupt(Isolate* isolate);
// Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as functions.
diff --git a/src/factory.cc b/src/factory.cc
index b2c7f84..3aacc59 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -4,11 +4,44 @@
#include "factory.h"
+#include "macro-assembler.h"
#include "isolate-inl.h"
+#include "v8conversions.h"
namespace v8 {
namespace internal {
+
+template<typename T>
+Handle<T> Factory::New(Handle<Map> map, AllocationSpace space) {
+ CALL_HEAP_FUNCTION(
+ isolate(),
+ isolate()->heap()->Allocate(*map, space),
+ T);
+}
+
+
+template<typename T>
+Handle<T> Factory::New(Handle<Map> map,
+ AllocationSpace space,
+ Handle<AllocationSite> allocation_site) {
+ CALL_HEAP_FUNCTION(
+ isolate(),
+ isolate()->heap()->Allocate(*map, space, *allocation_site),
+ T);
+}
+
+
+Handle<HeapObject> Factory::NewFillerObject(int size,
+ bool double_align,
+ AllocationSpace space) {
+ CALL_HEAP_FUNCTION(
+ isolate(),
+ isolate()->heap()->AllocateFillerObject(size, double_align, space),
+ HeapObject);
+}
+
+
Handle<Box> Factory::NewBox(Handle<Object> value) {
Handle<Box> result = Handle<Box>::cast(NewStruct(BOX_TYPE));
result->set_value(*value);
@@ -16,6 +49,16 @@
}
+Handle<Oddball> Factory::NewOddball(Handle<Map> map,
+ const char* to_string,
+ Handle<Object> to_number,
+ byte kind) {
+ Handle<Oddball> oddball = New<Oddball>(map, OLD_POINTER_SPACE);
+ Oddball::Initialize(isolate(), oddball, to_string, to_number, kind);
+ return oddball;
+}
+
+
Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
ASSERT(0 <= size);
CALL_HEAP_FUNCTION(
@@ -238,25 +281,50 @@
SubStringKey<uint16_t> > (SubStringKey<uint16_t>* key);
-Handle<String> Factory::NewStringFromOneByte(Vector<const uint8_t> string,
- PretenureFlag pretenure) {
- CALL_HEAP_FUNCTION(
+MaybeHandle<String> Factory::NewStringFromOneByte(Vector<const uint8_t> string,
+ PretenureFlag pretenure) {
+ int length = string.length();
+ if (length == 1) {
+ return LookupSingleCharacterStringFromCode(string[0]);
+ }
+ Handle<SeqOneByteString> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
isolate(),
- isolate()->heap()->AllocateStringFromOneByte(string, pretenure),
+ result,
+ NewRawOneByteString(string.length(), pretenure),
String);
+
+ DisallowHeapAllocation no_gc;
+ // Copy the characters into the new object.
+ CopyChars(SeqOneByteString::cast(*result)->GetChars(),
+ string.start(),
+ length);
+ return result;
}
-Handle<String> Factory::NewStringFromUtf8(Vector<const char> string,
- PretenureFlag pretenure) {
+MaybeHandle<String> Factory::NewStringFromUtf8(Vector<const char> string,
+ PretenureFlag pretenure) {
+ // Check for ASCII first since this is the common case.
+ const char* start = string.start();
+ int length = string.length();
+ int non_ascii_start = String::NonAsciiStart(start, length);
+ if (non_ascii_start >= length) {
+ // If the string is ASCII, we do not need to convert the characters
+ // since UTF8 is backwards compatible with ASCII.
+ return NewStringFromOneByte(Vector<const uint8_t>::cast(string), pretenure);
+ }
+ // Non-ASCII and we need to decode.
CALL_HEAP_FUNCTION(
isolate(),
- isolate()->heap()->AllocateStringFromUtf8(string, pretenure),
+ isolate()->heap()->AllocateStringFromUtf8Slow(string,
+ non_ascii_start,
+ pretenure),
String);
}
-Handle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
- PretenureFlag pretenure) {
+MaybeHandle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
+ PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateStringFromTwoByte(string, pretenure),
@@ -347,9 +415,7 @@
Handle<ConsString> Factory::NewRawConsString(String::Encoding encoding) {
Handle<Map> map = (encoding == String::ONE_BYTE_ENCODING)
? cons_ascii_string_map() : cons_string_map();
- CALL_HEAP_FUNCTION(isolate(),
- isolate()->heap()->Allocate(*map, NEW_SPACE),
- ConsString);
+ return New<ConsString>(map, NEW_SPACE);
}
@@ -371,8 +437,7 @@
// Make sure that an out of memory exception is thrown if the length
// of the new cons string is too large.
if (length > String::kMaxLength || length < 0) {
- return isolate()->Throw<String>(
- isolate()->factory()->NewInvalidStringLengthError());
+ return isolate()->Throw<String>(NewInvalidStringLengthError());
}
bool left_is_one_byte = left->IsOneByteRepresentation();
@@ -455,9 +520,7 @@
Handle<SlicedString> Factory::NewRawSlicedString(String::Encoding encoding) {
Handle<Map> map = (encoding == String::ONE_BYTE_ENCODING)
? sliced_ascii_string_map() : sliced_string_map();
- CALL_HEAP_FUNCTION(isolate(),
- isolate()->heap()->Allocate(*map, NEW_SPACE),
- SlicedString);
+ return New<SlicedString>(map, NEW_SPACE);
}
@@ -469,6 +532,8 @@
#endif
ASSERT(begin > 0 || end < str->length());
+ str = String::Flatten(str);
+
int length = end - begin;
if (length <= 0) return empty_string();
if (length == 1) {
@@ -503,28 +568,10 @@
int offset = begin;
- while (str->IsConsString()) {
- Handle<ConsString> cons = Handle<ConsString>::cast(str);
- int split = cons->first()->length();
- if (split <= offset) {
- // Slice is fully contained in the second part.
- str = Handle<String>(cons->second(), isolate());
- offset -= split; // Adjust for offset.
- continue;
- } else if (offset + length <= split) {
- // Slice is fully contained in the first part.
- str = Handle<String>(cons->first(), isolate());
- continue;
- }
- break;
- }
-
if (str->IsSlicedString()) {
Handle<SlicedString> slice = Handle<SlicedString>::cast(str);
str = Handle<String>(slice->parent(), isolate());
offset += slice->offset();
- } else {
- str = String::Flatten(str);
}
ASSERT(str->IsSeqString() || str->IsExternalString());
@@ -542,19 +589,45 @@
MaybeHandle<String> Factory::NewExternalStringFromAscii(
const ExternalAsciiString::Resource* resource) {
- CALL_HEAP_FUNCTION(
- isolate(),
- isolate()->heap()->AllocateExternalStringFromAscii(resource),
- String);
+ size_t length = resource->length();
+ if (length > static_cast<size_t>(String::kMaxLength)) {
+ isolate()->ThrowInvalidStringLength();
+ return MaybeHandle<String>();
+ }
+
+ Handle<Map> map = external_ascii_string_map();
+ Handle<ExternalAsciiString> external_string =
+ New<ExternalAsciiString>(map, NEW_SPACE);
+ external_string->set_length(static_cast<int>(length));
+ external_string->set_hash_field(String::kEmptyHashField);
+ external_string->set_resource(resource);
+
+ return external_string;
}
MaybeHandle<String> Factory::NewExternalStringFromTwoByte(
const ExternalTwoByteString::Resource* resource) {
- CALL_HEAP_FUNCTION(
- isolate(),
- isolate()->heap()->AllocateExternalStringFromTwoByte(resource),
- String);
+ size_t length = resource->length();
+ if (length > static_cast<size_t>(String::kMaxLength)) {
+ isolate()->ThrowInvalidStringLength();
+ return MaybeHandle<String>();
+ }
+
+ // For small strings we check whether the resource contains only
+ // one byte characters. If yes, we use a different string map.
+ static const size_t kOneByteCheckLengthLimit = 32;
+ bool is_one_byte = length <= kOneByteCheckLengthLimit &&
+ String::IsOneByte(resource->data(), static_cast<int>(length));
+ Handle<Map> map = is_one_byte ?
+ external_string_with_one_byte_data_map() : external_string_map();
+ Handle<ExternalTwoByteString> external_string =
+ New<ExternalTwoByteString>(map, NEW_SPACE);
+ external_string->set_length(static_cast<int>(length));
+ external_string->set_hash_field(String::kEmptyHashField);
+ external_string->set_resource(resource);
+
+ return external_string;
}
@@ -678,6 +751,15 @@
}
+Handle<CodeCache> Factory::NewCodeCache() {
+ Handle<CodeCache> code_cache =
+ Handle<CodeCache>::cast(NewStruct(CODE_CACHE_TYPE));
+ code_cache->set_default_cache(*empty_fixed_array(), SKIP_WRITE_BARRIER);
+ code_cache->set_normal_type_cache(*undefined_value(), SKIP_WRITE_BARRIER);
+ return code_cache;
+}
+
+
Handle<AliasedArgumentsEntry> Factory::NewAliasedArgumentsEntry(
int aliased_context_slot) {
Handle<AliasedArgumentsEntry> entry = Handle<AliasedArgumentsEntry>::cast(
@@ -814,10 +896,14 @@
Handle<AllocationSite> Factory::NewAllocationSite() {
- CALL_HEAP_FUNCTION(
- isolate(),
- isolate()->heap()->AllocateAllocationSite(),
- AllocationSite);
+ Handle<Map> map = allocation_site_map();
+ Handle<AllocationSite> site = New<AllocationSite>(map, OLD_POINTER_SPACE);
+ site->Initialize();
+
+ // Link the site
+ site->set_weak_next(isolate()->heap()->allocation_sites_list());
+ isolate()->heap()->set_allocation_sites_list(*site);
+ return site;
}
@@ -896,48 +982,21 @@
}
-Handle<JSFunction> Factory::BaseNewFunctionFromSharedFunctionInfo(
- Handle<SharedFunctionInfo> function_info,
- Handle<Map> function_map,
- PretenureFlag pretenure) {
- CALL_HEAP_FUNCTION(
- isolate(),
- isolate()->heap()->AllocateFunction(*function_map,
- *function_info,
- isolate()->heap()->the_hole_value(),
- pretenure),
- JSFunction);
-}
-
-
-static Handle<Map> MapForNewFunction(Isolate *isolate,
- Handle<SharedFunctionInfo> function_info) {
- Context *context = isolate->context()->native_context();
- int map_index = Context::FunctionMapIndex(function_info->strict_mode(),
- function_info->is_generator());
- return Handle<Map>(Map::cast(context->get(map_index)));
-}
-
-
Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
- Handle<SharedFunctionInfo> function_info,
+ Handle<SharedFunctionInfo> info,
Handle<Context> context,
PretenureFlag pretenure) {
- Handle<JSFunction> result = BaseNewFunctionFromSharedFunctionInfo(
- function_info,
- MapForNewFunction(isolate(), function_info),
- pretenure);
+ Handle<JSFunction> result = NewFunction(
+ info, context, the_hole_value(), pretenure);
- if (function_info->ic_age() != isolate()->heap()->global_ic_age()) {
- function_info->ResetForNewContext(isolate()->heap()->global_ic_age());
+ if (info->ic_age() != isolate()->heap()->global_ic_age()) {
+ info->ResetForNewContext(isolate()->heap()->global_ic_age());
}
- result->set_context(*context);
-
- int index = function_info->SearchOptimizedCodeMap(context->native_context(),
- BailoutId::None());
- if (!function_info->bound() && index < 0) {
- int number_of_literals = function_info->num_literals();
+ int index = info->SearchOptimizedCodeMap(context->native_context(),
+ BailoutId::None());
+ if (!info->bound() && index < 0) {
+ int number_of_literals = info->num_literals();
Handle<FixedArray> literals = NewFixedArray(number_of_literals, pretenure);
if (number_of_literals > 0) {
// Store the native context in the literals array prefix. This
@@ -951,10 +1010,9 @@
if (index > 0) {
// Caching of optimized code enabled and optimized code found.
- FixedArray* literals =
- function_info->GetLiteralsFromOptimizedCodeMap(index);
+ FixedArray* literals = info->GetLiteralsFromOptimizedCodeMap(index);
if (literals != NULL) result->set_literals(literals);
- Code* code = function_info->GetCodeFromOptimizedCodeMap(index);
+ Code* code = info->GetCodeFromOptimizedCodeMap(index);
ASSERT(!code->marked_for_deoptimization());
result->ReplaceCode(code);
return result;
@@ -963,9 +1021,9 @@
if (isolate()->use_crankshaft() &&
FLAG_always_opt &&
result->is_compiled() &&
- !function_info->is_toplevel() &&
- function_info->allows_lazy_compilation() &&
- !function_info->optimization_disabled() &&
+ !info->is_toplevel() &&
+ info->allows_lazy_compilation() &&
+ !info->optimization_disabled() &&
!isolate()->DebuggerHasBreakPoints()) {
result->MarkForOptimization();
}
@@ -975,17 +1033,26 @@
Handle<Object> Factory::NewNumber(double value,
PretenureFlag pretenure) {
- CALL_HEAP_FUNCTION(
- isolate(),
- isolate()->heap()->NumberFromDouble(value, pretenure), Object);
+ // We need to distinguish the minus zero value and this cannot be
+ // done after conversion to int. Doing this by comparing bit
+ // patterns is faster than using fpclassify() et al.
+ if (IsMinusZero(value)) return NewHeapNumber(-0.0, pretenure);
+
+ int int_value = FastD2I(value);
+ if (value == int_value && Smi::IsValid(int_value)) {
+ return handle(Smi::FromInt(int_value), isolate());
+ }
+
+ // Materialize the value in the heap.
+ return NewHeapNumber(value, pretenure);
}
Handle<Object> Factory::NewNumberFromInt(int32_t value,
PretenureFlag pretenure) {
- CALL_HEAP_FUNCTION(
- isolate(),
- isolate()->heap()->NumberFromInt32(value, pretenure), Object);
+ if (Smi::IsValid(value)) return handle(Smi::FromInt(value), isolate());
+ // Bypass NumberFromDouble to avoid various redundant checks.
+ return NewHeapNumber(FastI2D(value), pretenure);
}
@@ -1123,8 +1190,7 @@
} else {
buffer[kBufferSize - 1] = '\0';
}
- Handle<String> error_string = NewStringFromUtf8(CStrVector(buffer), TENURED);
- return error_string;
+ return NewStringFromUtf8(CStrVector(buffer), TENURED).ToHandleChecked();
}
@@ -1191,12 +1257,7 @@
Handle<Code> code,
bool force_initial_map) {
// Allocate the function
- Handle<JSFunction> function = NewFunction(name, the_hole_value());
-
- // Set up the code pointer in both the shared function info and in
- // the function itself.
- function->shared()->set_code(*code);
- function->set_code(*code);
+ Handle<JSFunction> function = NewFunction(name, code, the_hole_value());
if (force_initial_map ||
type != JS_OBJECT_TYPE ||
@@ -1222,12 +1283,7 @@
Handle<Code> code,
bool force_initial_map) {
// Allocate the function.
- Handle<JSFunction> function = NewFunction(name, prototype);
-
- // Set up the code pointer in both the shared function info and in
- // the function itself.
- function->shared()->set_code(*code);
- function->set_code(*code);
+ Handle<JSFunction> function = NewFunction(name, code, prototype);
if (force_initial_map ||
type != JS_OBJECT_TYPE ||
@@ -1244,14 +1300,15 @@
}
-Handle<JSFunction> Factory::NewFunctionWithoutPrototype(Handle<String> name,
- Handle<Code> code) {
- Handle<JSFunction> function = NewFunctionWithoutPrototype(name, SLOPPY);
- function->shared()->set_code(*code);
- function->set_code(*code);
- ASSERT(!function->has_initial_map());
- ASSERT(!function->has_prototype());
- return function;
+Handle<JSObject> Factory::NewIteratorResultObject(Handle<Object> value,
+ bool done) {
+ Handle<Map> map(isolate()->native_context()->iterator_result_map());
+ Handle<JSObject> result = NewJSObjectFromMap(map, NOT_TENURED, false);
+ result->InObjectPropertyAtPut(
+ JSGeneratorObject::kResultValuePropertyIndex, *value);
+ result->InObjectPropertyAtPut(
+ JSGeneratorObject::kResultDonePropertyIndex, *ToBoolean(done));
+ return result;
}
@@ -1271,17 +1328,77 @@
}
+Handle<Code> NewCodeHelper(Isolate* isolate, int object_size, bool immovable) {
+ CALL_HEAP_FUNCTION(isolate,
+ isolate->heap()->AllocateCode(object_size, immovable),
+ Code);
+}
+
+
Handle<Code> Factory::NewCode(const CodeDesc& desc,
Code::Flags flags,
Handle<Object> self_ref,
bool immovable,
bool crankshafted,
int prologue_offset) {
- CALL_HEAP_FUNCTION(isolate(),
- isolate()->heap()->CreateCode(
- desc, flags, self_ref, immovable, crankshafted,
- prologue_offset),
- Code);
+ Handle<ByteArray> reloc_info = NewByteArray(desc.reloc_size, TENURED);
+ Handle<ConstantPoolArray> constant_pool =
+ desc.origin->NewConstantPool(isolate());
+
+ // Compute size.
+ int body_size = RoundUp(desc.instr_size, kObjectAlignment);
+ int obj_size = Code::SizeFor(body_size);
+
+ Handle<Code> code = NewCodeHelper(isolate(), obj_size, immovable);
+ ASSERT(!isolate()->code_range()->exists() ||
+ isolate()->code_range()->contains(code->address()));
+
+ // The code object has not been fully initialized yet. We rely on the
+ // fact that no allocation will happen from this point on.
+ DisallowHeapAllocation no_gc;
+ code->set_gc_metadata(Smi::FromInt(0));
+ code->set_ic_age(isolate()->heap()->global_ic_age());
+ code->set_instruction_size(desc.instr_size);
+ code->set_relocation_info(*reloc_info);
+ code->set_flags(flags);
+ code->set_raw_kind_specific_flags1(0);
+ code->set_raw_kind_specific_flags2(0);
+ code->set_is_crankshafted(crankshafted);
+ code->set_deoptimization_data(*empty_fixed_array(), SKIP_WRITE_BARRIER);
+ code->set_raw_type_feedback_info(*undefined_value());
+ code->set_next_code_link(*undefined_value());
+ code->set_handler_table(*empty_fixed_array(), SKIP_WRITE_BARRIER);
+ code->set_prologue_offset(prologue_offset);
+ if (code->kind() == Code::OPTIMIZED_FUNCTION) {
+ code->set_marked_for_deoptimization(false);
+ }
+
+ desc.origin->PopulateConstantPool(*constant_pool);
+ code->set_constant_pool(*constant_pool);
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ if (code->kind() == Code::FUNCTION) {
+ code->set_has_debug_break_slots(isolate()->debugger()->IsDebuggerActive());
+ }
+#endif
+
+ // Allow self references to created code object by patching the handle to
+ // point to the newly allocated Code object.
+ if (!self_ref.is_null()) *(self_ref.location()) = *code;
+
+ // Migrate generated code.
+ // The generated code can contain Object** values (typically from handles)
+ // that are dereferenced during the copy to point directly to the actual heap
+ // objects. These pointers can include references to the code object itself,
+ // through the self_reference parameter.
+ code->CopyFrom(desc);
+
+#ifdef VERIFY_HEAP
+ if (FLAG_verify_heap) {
+ code->Verify();
+ }
+#endif
+ return code;
}
@@ -1332,14 +1449,6 @@
}
-static Handle<GlobalObject> NewGlobalObjectFromMap(Isolate* isolate,
- Handle<Map> map) {
- CALL_HEAP_FUNCTION(isolate,
- isolate->heap()->Allocate(*map, OLD_POINTER_SPACE),
- GlobalObject);
-}
-
-
Handle<GlobalObject> Factory::NewGlobalObject(Handle<JSFunction> constructor) {
ASSERT(constructor->has_initial_map());
Handle<Map> map(constructor->initial_map());
@@ -1378,7 +1487,7 @@
}
// Allocate the global object and initialize it with the backing store.
- Handle<GlobalObject> global = NewGlobalObjectFromMap(isolate(), map);
+ Handle<GlobalObject> global = New<GlobalObject>(map, OLD_POINTER_SPACE);
isolate()->heap()->InitializeJSObjectFromMap(*global, *dictionary, *map);
// Create a new map for the global object.
@@ -1438,8 +1547,7 @@
int length,
PretenureFlag pretenure) {
ASSERT(length <= elements->length());
- Handle<JSArray> array =
- isolate()->factory()->NewJSArray(elements_kind, pretenure);
+ Handle<JSArray> array = NewJSArray(elements_kind, pretenure);
array->set_elements(*elements);
array->set_length(Smi::FromInt(length));
@@ -1547,26 +1655,132 @@
Handle<JSProxy> Factory::NewJSProxy(Handle<Object> handler,
Handle<Object> prototype) {
- CALL_HEAP_FUNCTION(
- isolate(),
- isolate()->heap()->AllocateJSProxy(*handler, *prototype),
- JSProxy);
+ // Allocate map.
+ // TODO(rossberg): Once we optimize proxies, think about a scheme to share
+ // maps. Will probably depend on the identity of the handler object, too.
+ Handle<Map> map = NewMap(JS_PROXY_TYPE, JSProxy::kSize);
+ map->set_prototype(*prototype);
+
+ // Allocate the proxy object.
+ Handle<JSProxy> result = New<JSProxy>(map, NEW_SPACE);
+ result->InitializeBody(map->instance_size(), Smi::FromInt(0));
+ result->set_handler(*handler);
+ result->set_hash(*undefined_value(), SKIP_WRITE_BARRIER);
+ return result;
+}
+
+
+Handle<JSProxy> Factory::NewJSFunctionProxy(Handle<Object> handler,
+ Handle<Object> call_trap,
+ Handle<Object> construct_trap,
+ Handle<Object> prototype) {
+ // Allocate map.
+ // TODO(rossberg): Once we optimize proxies, think about a scheme to share
+ // maps. Will probably depend on the identity of the handler object, too.
+ Handle<Map> map = NewMap(JS_FUNCTION_PROXY_TYPE, JSFunctionProxy::kSize);
+ map->set_prototype(*prototype);
+
+ // Allocate the proxy object.
+ Handle<JSFunctionProxy> result = New<JSFunctionProxy>(map, NEW_SPACE);
+ result->InitializeBody(map->instance_size(), Smi::FromInt(0));
+ result->set_handler(*handler);
+ result->set_hash(*undefined_value(), SKIP_WRITE_BARRIER);
+ result->set_call_trap(*call_trap);
+ result->set_construct_trap(*construct_trap);
+ return result;
+}
+
+
+void Factory::ReinitializeJSReceiver(Handle<JSReceiver> object,
+ InstanceType type,
+ int size) {
+ ASSERT(type >= FIRST_JS_OBJECT_TYPE);
+
+ // Allocate fresh map.
+ // TODO(rossberg): Once we optimize proxies, cache these maps.
+ Handle<Map> map = NewMap(type, size);
+
+ // Check that the receiver has at least the size of the fresh object.
+ int size_difference = object->map()->instance_size() - map->instance_size();
+ ASSERT(size_difference >= 0);
+
+ map->set_prototype(object->map()->prototype());
+
+ // Allocate the backing storage for the properties.
+ int prop_size = map->unused_property_fields() - map->inobject_properties();
+ Handle<FixedArray> properties = NewFixedArray(prop_size, TENURED);
+
+ Heap* heap = isolate()->heap();
+ MaybeHandle<SharedFunctionInfo> shared;
+ if (type == JS_FUNCTION_TYPE) {
+ OneByteStringKey key(STATIC_ASCII_VECTOR("<freezing call trap>"),
+ heap->HashSeed());
+ Handle<String> name = InternalizeStringWithKey(&key);
+ shared = NewSharedFunctionInfo(name);
+ }
+
+ // In order to keep heap in consistent state there must be no allocations
+ // before object re-initialization is finished and filler object is installed.
+ DisallowHeapAllocation no_allocation;
+
+ // Reset the map for the object.
+ object->set_map(*map);
+ Handle<JSObject> jsobj = Handle<JSObject>::cast(object);
+
+ // Reinitialize the object from the constructor map.
+ heap->InitializeJSObjectFromMap(*jsobj, *properties, *map);
+
+ // Functions require some minimal initialization.
+ if (type == JS_FUNCTION_TYPE) {
+ map->set_function_with_prototype(true);
+ Handle<JSFunction> js_function = Handle<JSFunction>::cast(object);
+ Handle<Context> context(isolate()->context()->native_context());
+ InitializeFunction(js_function, shared.ToHandleChecked(),
+ context, null_value());
+ }
+
+ // Put in filler if the new object is smaller than the old.
+ if (size_difference > 0) {
+ heap->CreateFillerObjectAt(
+ object->address() + map->instance_size(), size_difference);
+ }
+}
+
+
+void Factory::ReinitializeJSGlobalProxy(Handle<JSGlobalProxy> object,
+ Handle<JSFunction> constructor) {
+ ASSERT(constructor->has_initial_map());
+ Handle<Map> map(constructor->initial_map(), isolate());
+
+ // Check that the already allocated object has the same size and type as
+ // objects allocated using the constructor.
+ ASSERT(map->instance_size() == object->map()->instance_size());
+ ASSERT(map->instance_type() == object->map()->instance_type());
+
+ // Allocate the backing storage for the properties.
+ int prop_size = map->unused_property_fields() - map->inobject_properties();
+ Handle<FixedArray> properties = NewFixedArray(prop_size, TENURED);
+
+ // In order to keep heap in consistent state there must be no allocations
+ // before object re-initialization is finished.
+ DisallowHeapAllocation no_allocation;
+
+ // Reset the map for the object.
+ object->set_map(constructor->initial_map());
+
+ Heap* heap = isolate()->heap();
+ // Reinitialize the object from the constructor map.
+ heap->InitializeJSObjectFromMap(*object, *properties, *map);
}
void Factory::BecomeJSObject(Handle<JSReceiver> object) {
- CALL_HEAP_FUNCTION_VOID(
- isolate(),
- isolate()->heap()->ReinitializeJSReceiver(
- *object, JS_OBJECT_TYPE, JSObject::kHeaderSize));
+ ReinitializeJSReceiver(object, JS_OBJECT_TYPE, JSObject::kHeaderSize);
}
void Factory::BecomeJSFunction(Handle<JSReceiver> object) {
- CALL_HEAP_FUNCTION_VOID(
- isolate(),
- isolate()->heap()->ReinitializeJSReceiver(
- *object, JS_FUNCTION_TYPE, JSFunction::kSize));
+ ReinitializeJSReceiver(object, JS_FUNCTION_TYPE, JSFunction::kSize);
}
@@ -1602,33 +1816,133 @@
int end_position,
Handle<Object> script,
Handle<Object> stack_frames) {
- CALL_HEAP_FUNCTION(isolate(),
- isolate()->heap()->AllocateJSMessageObject(*type,
- *arguments,
- start_position,
- end_position,
- *script,
- *stack_frames),
- JSMessageObject);
+ Handle<Map> map = message_object_map();
+ Handle<JSMessageObject> message = New<JSMessageObject>(map, NEW_SPACE);
+ message->set_properties(*empty_fixed_array(), SKIP_WRITE_BARRIER);
+ message->initialize_elements();
+ message->set_elements(*empty_fixed_array(), SKIP_WRITE_BARRIER);
+ message->set_type(*type);
+ message->set_arguments(*arguments);
+ message->set_start_position(start_position);
+ message->set_end_position(end_position);
+ message->set_script(*script);
+ message->set_stack_frames(*stack_frames);
+ return message;
}
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
- CALL_HEAP_FUNCTION(isolate(),
- isolate()->heap()->AllocateSharedFunctionInfo(*name),
- SharedFunctionInfo);
+ Handle<Map> map = shared_function_info_map();
+ Handle<SharedFunctionInfo> share = New<SharedFunctionInfo>(map,
+ OLD_POINTER_SPACE);
+
+ // Set pointer fields.
+ share->set_name(*name);
+ Code* illegal = isolate()->builtins()->builtin(Builtins::kIllegal);
+ share->set_code(illegal);
+ share->set_optimized_code_map(Smi::FromInt(0));
+ share->set_scope_info(ScopeInfo::Empty(isolate()));
+ Code* construct_stub =
+ isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric);
+ share->set_construct_stub(construct_stub);
+ share->set_instance_class_name(*Object_string());
+ share->set_function_data(*undefined_value(), SKIP_WRITE_BARRIER);
+ share->set_script(*undefined_value(), SKIP_WRITE_BARRIER);
+ share->set_debug_info(*undefined_value(), SKIP_WRITE_BARRIER);
+ share->set_inferred_name(*empty_string(), SKIP_WRITE_BARRIER);
+ share->set_initial_map(*undefined_value(), SKIP_WRITE_BARRIER);
+ share->set_profiler_ticks(0);
+ share->set_ast_node_count(0);
+ share->set_counters(0);
+
+ // Set integer fields (smi or int, depending on the architecture).
+ share->set_length(0);
+ share->set_formal_parameter_count(0);
+ share->set_expected_nof_properties(0);
+ share->set_num_literals(0);
+ share->set_start_position_and_type(0);
+ share->set_end_position(0);
+ share->set_function_token_position(0);
+ // All compiler hints default to false or 0.
+ share->set_compiler_hints(0);
+ share->set_opt_count_and_bailout_reason(0);
+
+ return share;
}
-Handle<String> Factory::NumberToString(Handle<Object> number) {
- CALL_HEAP_FUNCTION(isolate(),
- isolate()->heap()->NumberToString(*number), String);
+static inline int NumberCacheHash(Handle<FixedArray> cache,
+ Handle<Object> number) {
+ int mask = (cache->length() >> 1) - 1;
+ if (number->IsSmi()) {
+ return Handle<Smi>::cast(number)->value() & mask;
+ } else {
+ DoubleRepresentation rep(number->Number());
+ return
+ (static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32)) & mask;
+ }
}
-Handle<String> Factory::Uint32ToString(uint32_t value) {
- CALL_HEAP_FUNCTION(isolate(),
- isolate()->heap()->Uint32ToString(value), String);
+Handle<Object> Factory::GetNumberStringCache(Handle<Object> number) {
+ DisallowHeapAllocation no_gc;
+ int hash = NumberCacheHash(number_string_cache(), number);
+ Object* key = number_string_cache()->get(hash * 2);
+ if (key == *number || (key->IsHeapNumber() && number->IsHeapNumber() &&
+ key->Number() == number->Number())) {
+ return Handle<String>(
+ String::cast(number_string_cache()->get(hash * 2 + 1)), isolate());
+ }
+ return undefined_value();
+}
+
+
+void Factory::SetNumberStringCache(Handle<Object> number,
+ Handle<String> string) {
+ int hash = NumberCacheHash(number_string_cache(), number);
+ if (number_string_cache()->get(hash * 2) != *undefined_value()) {
+ int full_size = isolate()->heap()->FullSizeNumberStringCacheLength();
+ if (number_string_cache()->length() != full_size) {
+ // The first time we have a hash collision, we move to the full sized
+ // number string cache. The idea is to have a small number string
+ // 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() || FLAG_extra_code != NULL);
+ Handle<FixedArray> new_cache = NewFixedArray(full_size, TENURED);
+ isolate()->heap()->set_number_string_cache(*new_cache);
+ return;
+ }
+ }
+ number_string_cache()->set(hash * 2, *number);
+ number_string_cache()->set(hash * 2 + 1, *string);
+}
+
+
+Handle<String> Factory::NumberToString(Handle<Object> number,
+ bool check_number_string_cache) {
+ isolate()->counters()->number_to_string_runtime()->Increment();
+ if (check_number_string_cache) {
+ Handle<Object> cached = GetNumberStringCache(number);
+ if (!cached->IsUndefined()) return Handle<String>::cast(cached);
+ }
+
+ char arr[100];
+ Vector<char> buffer(arr, ARRAY_SIZE(arr));
+ const char* str;
+ if (number->IsSmi()) {
+ int num = Handle<Smi>::cast(number)->value();
+ str = IntToCString(num, buffer);
+ } else {
+ double num = Handle<HeapNumber>::cast(number)->value();
+ str = DoubleToCString(num, buffer);
+ }
+
+ // We tenure the allocated string since it is referenced from the
+ // number-string cache which lives in the old space.
+ Handle<String> js_string = NewStringFromAsciiChecked(str, TENURED);
+ SetNumberStringCache(number, js_string);
+ return js_string;
}
@@ -1652,48 +1966,70 @@
}
-Handle<JSFunction> Factory::NewFunctionHelper(Handle<String> name,
- Handle<Object> prototype) {
- Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
- CALL_HEAP_FUNCTION(
- isolate(),
- isolate()->heap()->AllocateFunction(*isolate()->sloppy_function_map(),
- *function_share,
- *prototype),
- JSFunction);
+void Factory::InitializeFunction(Handle<JSFunction> function,
+ Handle<SharedFunctionInfo> info,
+ Handle<Context> context,
+ MaybeHandle<Object> maybe_prototype) {
+ function->initialize_properties();
+ function->initialize_elements();
+ function->set_shared(*info);
+ function->set_code(info->code());
+ function->set_context(*context);
+ Handle<Object> prototype;
+ if (maybe_prototype.ToHandle(&prototype)) {
+ ASSERT(!prototype->IsMap());
+ } else {
+ prototype = the_hole_value();
+ }
+ function->set_prototype_or_initial_map(*prototype);
+ function->set_literals_or_bindings(*empty_fixed_array());
+ function->set_next_function_link(*undefined_value());
+}
+
+
+static Handle<Map> MapForNewFunction(Isolate* isolate,
+ Handle<SharedFunctionInfo> function_info,
+ MaybeHandle<Object> maybe_prototype) {
+ if (maybe_prototype.is_null()) {
+ return function_info->strict_mode() == SLOPPY
+ ? isolate->sloppy_function_without_prototype_map()
+ : isolate->strict_function_without_prototype_map();
+ }
+
+ Context* context = isolate->context()->native_context();
+ int map_index = Context::FunctionMapIndex(function_info->strict_mode(),
+ function_info->is_generator());
+ return Handle<Map>(Map::cast(context->get(map_index)));
+}
+
+
+Handle<JSFunction> Factory::NewFunction(Handle<SharedFunctionInfo> info,
+ Handle<Context> context,
+ MaybeHandle<Object> maybe_prototype,
+ PretenureFlag pretenure) {
+ Handle<Map> map = MapForNewFunction(isolate(), info, maybe_prototype);
+ AllocationSpace space = pretenure == TENURED ? OLD_POINTER_SPACE : NEW_SPACE;
+ Handle<JSFunction> result = New<JSFunction>(map, space);
+ InitializeFunction(result, info, context, maybe_prototype);
+ return result;
}
Handle<JSFunction> Factory::NewFunction(Handle<String> name,
- Handle<Object> prototype) {
- Handle<JSFunction> fun = NewFunctionHelper(name, prototype);
- fun->set_context(isolate()->context()->native_context());
- return fun;
+ Handle<Code> code,
+ MaybeHandle<Object> maybe_prototype) {
+ Handle<SharedFunctionInfo> info = NewSharedFunctionInfo(name);
+ info->set_code(*code);
+ Handle<Context> context(isolate()->context()->native_context());
+ return NewFunction(info, context, maybe_prototype);
}
-Handle<JSFunction> Factory::NewFunctionWithoutPrototypeHelper(
- Handle<String> name,
- StrictMode strict_mode) {
- Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
- Handle<Map> map = strict_mode == SLOPPY
- ? isolate()->sloppy_function_without_prototype_map()
- : isolate()->strict_function_without_prototype_map();
- CALL_HEAP_FUNCTION(isolate(),
- isolate()->heap()->AllocateFunction(
- *map,
- *function_share,
- *the_hole_value()),
- JSFunction);
-}
-
-
-Handle<JSFunction> Factory::NewFunctionWithoutPrototype(
- Handle<String> name,
- StrictMode strict_mode) {
- Handle<JSFunction> fun = NewFunctionWithoutPrototypeHelper(name, strict_mode);
- fun->set_context(isolate()->context()->native_context());
- return fun;
+Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
+ Handle<Object> prototype) {
+ Handle<SharedFunctionInfo> info = NewSharedFunctionInfo(name);
+ Handle<Context> context(isolate()->context()->native_context());
+ return NewFunction(info, context, prototype);
}
@@ -1775,12 +2111,8 @@
break;
}
- Handle<JSFunction> result =
- NewFunction(Factory::empty_string(),
- type,
- instance_size,
- code,
- true);
+ Handle<JSFunction> result = NewFunction(
+ Factory::empty_string(), type, instance_size, code, true);
// Set length.
result->shared()->set_length(obj->length());
@@ -1892,7 +2224,7 @@
// Install accumulated static accessors
for (int i = 0; i < valid_descriptors; i++) {
Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
- JSObject::SetAccessor(result, accessor);
+ JSObject::SetAccessor(result, accessor).Assert();
}
ASSERT(result->shared()->IsApiFunction());
@@ -1908,24 +2240,13 @@
}
-MUST_USE_RESULT static MaybeObject* UpdateMapCacheWith(Context* context,
- FixedArray* keys,
- Map* map) {
- Object* result;
- { MaybeObject* maybe_result =
- MapCache::cast(context->map_cache())->Put(keys, map);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- context->set_map_cache(MapCache::cast(result));
- return result;
-}
-
-
Handle<MapCache> Factory::AddToMapCache(Handle<Context> context,
Handle<FixedArray> keys,
Handle<Map> map) {
- CALL_HEAP_FUNCTION(isolate(),
- UpdateMapCacheWith(*context, *keys, *map), MapCache);
+ Handle<MapCache> map_cache = handle(MapCache::cast(context->map_cache()));
+ Handle<MapCache> result = MapCache::Put(map_cache, keys, map);
+ context->set_map_cache(*result);
+ return result;
}
@@ -2012,4 +2333,5 @@
return value ? true_value() : false_value();
}
+
} } // namespace v8::internal
diff --git a/src/factory.h b/src/factory.h
index 107cbfd..f29aac4 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -14,6 +14,11 @@
class Factory V8_FINAL {
public:
+ Handle<Oddball> NewOddball(Handle<Map> map,
+ const char* to_string,
+ Handle<Object> to_number,
+ byte kind);
+
// Allocates a fixed array initialized with undefined values.
Handle<FixedArray> NewFixedArray(
int size,
@@ -113,11 +118,28 @@
// two byte.
//
// ASCII strings are pretenured when used as keys in the SourceCodeCache.
- Handle<String> NewStringFromOneByte(
+ MUST_USE_RESULT MaybeHandle<String> NewStringFromOneByte(
Vector<const uint8_t> str,
PretenureFlag pretenure = NOT_TENURED);
+
+ template<size_t N>
+ inline Handle<String> NewStringFromStaticAscii(
+ const char (&str)[N],
+ PretenureFlag pretenure = NOT_TENURED) {
+ ASSERT(N == StrLength(str) + 1);
+ return NewStringFromOneByte(
+ STATIC_ASCII_VECTOR(str), pretenure).ToHandleChecked();
+ }
+
+ inline Handle<String> NewStringFromAsciiChecked(
+ const char* str,
+ PretenureFlag pretenure = NOT_TENURED) {
+ return NewStringFromOneByte(
+ OneByteVector(str), pretenure).ToHandleChecked();
+ }
+
// TODO(dcarney): remove this function.
- inline Handle<String> NewStringFromAscii(
+ MUST_USE_RESULT inline MaybeHandle<String> NewStringFromAscii(
Vector<const char> str,
PretenureFlag pretenure = NOT_TENURED) {
return NewStringFromOneByte(Vector<const uint8_t>::cast(str), pretenure);
@@ -125,11 +147,11 @@
// UTF8 strings are pretenured when used for regexp literal patterns and
// flags in the parser.
- Handle<String> NewStringFromUtf8(
+ MUST_USE_RESULT MaybeHandle<String> NewStringFromUtf8(
Vector<const char> str,
PretenureFlag pretenure = NOT_TENURED);
- Handle<String> NewStringFromTwoByte(
+ MUST_USE_RESULT MaybeHandle<String> NewStringFromTwoByte(
Vector<const uc16> str,
PretenureFlag pretenure = NOT_TENURED);
@@ -171,7 +193,8 @@
// Creates a new external String object. There are two String encodings
// in the system: ASCII and two byte. Unlike other String types, it does
// not make sense to have a UTF-8 factory function for external strings,
- // because we cannot change the underlying buffer.
+ // because we cannot change the underlying buffer. Note that these strings
+ // are backed by a string resource that resides outside the V8 heap.
MUST_USE_RESULT MaybeHandle<String> NewExternalStringFromAscii(
const ExternalAsciiString::Resource* resource);
MUST_USE_RESULT MaybeHandle<String> NewExternalStringFromTwoByte(
@@ -214,6 +237,8 @@
// the old generation).
Handle<Struct> NewStruct(InstanceType type);
+ Handle<CodeCache> NewCodeCache();
+
Handle<AliasedArgumentsEntry> NewAliasedArgumentsEntry(
int aliased_context_slot);
@@ -253,6 +278,7 @@
Handle<PropertyCell> NewPropertyCell(Handle<Object> value);
+ // Allocate a tenured AllocationSite. It's payload is null.
Handle<AllocationSite> NewAllocationSite();
Handle<Map> NewMap(
@@ -260,6 +286,10 @@
int instance_size,
ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND);
+ Handle<HeapObject> NewFillerObject(int size,
+ bool double_align,
+ AllocationSpace space);
+
Handle<JSObject> NewFunctionPrototype(Handle<JSFunction> function);
Handle<FixedArray> CopyFixedArray(Handle<FixedArray> array);
@@ -279,6 +309,7 @@
Handle<ConstantPoolArray> array);
// Numbers (e.g. literals) are pretenured by the parser.
+ // The return value may be a smi or a heap number.
Handle<Object> NewNumber(double value,
PretenureFlag pretenure = NOT_TENURED);
@@ -323,9 +354,6 @@
bool allocate_properties = true,
Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
- Handle<JSObject> NewJSObjectFromMapForDeoptimizer(
- Handle<Map> map, PretenureFlag pretenure = NOT_TENURED);
-
// JS modules are pretenured.
Handle<JSModule> NewJSModule(Handle<Context> context,
Handle<ScopeInfo> scope_info);
@@ -386,37 +414,68 @@
Handle<JSDataView> NewJSDataView();
+ // Allocates a Harmony proxy.
Handle<JSProxy> NewJSProxy(Handle<Object> handler, Handle<Object> prototype);
+ // Allocates a Harmony function proxy.
+ Handle<JSProxy> NewJSFunctionProxy(Handle<Object> handler,
+ Handle<Object> call_trap,
+ Handle<Object> construct_trap,
+ Handle<Object> prototype);
+
+ // Reinitialize a JSReceiver into an (empty) JS object of respective type and
+ // size, but keeping the original prototype. The receiver must have at least
+ // the size of the new object. The object is reinitialized and behaves as an
+ // object that has been freshly allocated.
+ void ReinitializeJSReceiver(
+ Handle<JSReceiver> object, InstanceType type, int size);
+
+ // Reinitialize an JSGlobalProxy based on a constructor. The object
+ // must have the same size as objects allocated using the
+ // constructor. The object is reinitialized and behaves as an
+ // object that has been freshly allocated using the constructor.
+ void ReinitializeJSGlobalProxy(Handle<JSGlobalProxy> global,
+ Handle<JSFunction> constructor);
+
// Change the type of the argument into a JS object/function and reinitialize.
void BecomeJSObject(Handle<JSReceiver> object);
void BecomeJSFunction(Handle<JSReceiver> object);
Handle<JSFunction> NewFunction(Handle<String> name,
- Handle<Object> prototype);
+ Handle<Code> code,
+ MaybeHandle<Object> maybe_prototype =
+ MaybeHandle<Object>());
- Handle<JSFunction> NewFunctionWithoutPrototype(
- Handle<String> name,
- StrictMode strict_mode);
-
- Handle<JSFunction> NewFunction(Handle<Object> super, bool is_global);
-
- Handle<JSFunction> BaseNewFunctionFromSharedFunctionInfo(
- Handle<SharedFunctionInfo> function_info,
- Handle<Map> function_map,
- PretenureFlag pretenure);
+ Handle<JSFunction> NewFunctionWithPrototype(Handle<String> name,
+ Handle<Object> prototype);
Handle<JSFunction> NewFunctionFromSharedFunctionInfo(
Handle<SharedFunctionInfo> function_info,
Handle<Context> context,
PretenureFlag pretenure = TENURED);
+ Handle<JSFunction> NewFunction(Handle<String> name,
+ InstanceType type,
+ int instance_size,
+ Handle<Code> code,
+ bool force_initial_map);
+
+ Handle<JSFunction> NewFunctionWithPrototype(Handle<String> name,
+ InstanceType type,
+ int instance_size,
+ Handle<JSObject> prototype,
+ Handle<Code> code,
+ bool force_initial_map);
+
// Create a serialized scope info.
Handle<ScopeInfo> NewScopeInfo(int length);
// Create an External object for V8's external API.
Handle<JSObject> NewExternal(void* value);
+ // The reference to the Code object is stored in self_reference.
+ // This allows generated code to reference its own Code object
+ // by containing this handle.
Handle<Code> NewCode(const CodeDesc& desc,
Code::Flags flags,
Handle<Object> self_reference,
@@ -465,29 +524,14 @@
Handle<Object> NewEvalError(const char* message,
Vector< Handle<Object> > args);
+ Handle<JSObject> NewIteratorResultObject(Handle<Object> value, bool done);
- Handle<JSFunction> NewFunction(Handle<String> name,
- InstanceType type,
- int instance_size,
- Handle<Code> code,
- bool force_initial_map);
+ Handle<String> NumberToString(Handle<Object> number,
+ bool check_number_string_cache = true);
- Handle<JSFunction> NewFunction(Handle<Map> function_map,
- Handle<SharedFunctionInfo> shared, Handle<Object> prototype);
-
-
- Handle<JSFunction> NewFunctionWithPrototype(Handle<String> name,
- InstanceType type,
- int instance_size,
- Handle<JSObject> prototype,
- Handle<Code> code,
- bool force_initial_map);
-
- Handle<JSFunction> NewFunctionWithoutPrototype(Handle<String> name,
- Handle<Code> code);
-
- Handle<String> NumberToString(Handle<Object> number);
- Handle<String> Uint32ToString(uint32_t value);
+ Handle<String> Uint32ToString(uint32_t value) {
+ return NumberToString(NewNumberFromUint(value));
+ }
enum ApiInstanceType {
JavaScriptObject,
@@ -535,6 +579,7 @@
return Handle<String>(&isolate()->heap()->hidden_string_);
}
+ // Allocates a new SharedFunctionInfo object.
Handle<SharedFunctionInfo> NewSharedFunctionInfo(
Handle<String> name,
int number_of_literals,
@@ -543,6 +588,7 @@
Handle<ScopeInfo> scope_info);
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
+ // Allocates a new JSMessageObject object.
Handle<JSMessageObject> NewJSMessageObject(
Handle<String> type,
Handle<JSArray> arguments,
@@ -597,12 +643,31 @@
private:
Isolate* isolate() { return reinterpret_cast<Isolate*>(this); }
- Handle<JSFunction> NewFunctionHelper(Handle<String> name,
- Handle<Object> prototype);
+ // Creates a heap object based on the map. The fields of the heap object are
+ // not initialized by New<>() functions. It's the responsibility of the caller
+ // to do that.
+ template<typename T>
+ Handle<T> New(Handle<Map> map, AllocationSpace space);
- Handle<JSFunction> NewFunctionWithoutPrototypeHelper(
- Handle<String> name,
- StrictMode strict_mode);
+ template<typename T>
+ Handle<T> New(Handle<Map> map,
+ AllocationSpace space,
+ Handle<AllocationSite> allocation_site);
+
+ // Initializes a function with a shared part and prototype.
+ // Note: this code was factored out of NewFunction such that other parts of
+ // the VM could use it. Specifically, a function that creates instances of
+ // type JS_FUNCTION_TYPE benefit from the use of this function.
+ inline void InitializeFunction(Handle<JSFunction> function,
+ Handle<SharedFunctionInfo> info,
+ Handle<Context> context,
+ MaybeHandle<Object> maybe_prototype);
+
+ // Creates a function initialized with a shared part.
+ inline Handle<JSFunction> NewFunction(Handle<SharedFunctionInfo> info,
+ Handle<Context> context,
+ MaybeHandle<Object> maybe_prototype,
+ PretenureFlag pretenure = TENURED);
// Create a new map cache.
Handle<MapCache> NewMapCache(int at_least_space_for);
@@ -611,6 +676,13 @@
Handle<MapCache> AddToMapCache(Handle<Context> context,
Handle<FixedArray> keys,
Handle<Map> map);
+
+ // Attempt to find the number in a small cache. If we finds it, return
+ // the string representation of the number. Otherwise return undefined.
+ Handle<Object> GetNumberStringCache(Handle<Object> number);
+
+ // Update the cache with a new number-string pair.
+ void SetNumberStringCache(Handle<Object> number, Handle<String> string);
};
} } // namespace v8::internal
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 1942c35..429ecbd 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -233,6 +233,9 @@
DEFINE_implication(track_double_fields, track_fields)
DEFINE_implication(track_heap_object_fields, track_fields)
DEFINE_implication(track_computed_fields, track_fields)
+DEFINE_bool(track_field_types, false, "track field types")
+DEFINE_implication(track_field_types, track_fields)
+DEFINE_implication(track_field_types, track_heap_object_fields)
DEFINE_bool(smi_binop, true, "support smi representation in binary operations")
// Flags for optimization types.
diff --git a/src/flags.cc b/src/flags.cc
index 8e42206..7feb51f 100644
--- a/src/flags.cc
+++ b/src/flags.cc
@@ -545,7 +545,7 @@
void FlagList::PrintHelp() {
#if V8_TARGET_ARCH_ARM
CpuFeatures::PrintTarget();
- CpuFeatures::Probe();
+ CpuFeatures::ProbeWithoutIsolate();
CpuFeatures::PrintFeatures();
#endif // V8_TARGET_ARCH_ARM
diff --git a/src/frames.cc b/src/frames.cc
index 0c47de9..73526d8 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -806,7 +806,6 @@
bool print_args,
bool print_line_number) {
// constructor calls
- HandleScope scope(isolate);
DisallowHeapAllocation no_allocation;
JavaScriptFrameIterator it(isolate);
while (!it.done()) {
@@ -827,8 +826,8 @@
int source_pos = code->SourcePosition(pc);
Object* maybe_script = shared->script();
if (maybe_script->IsScript()) {
- Handle<Script> script(Script::cast(maybe_script));
- int line = GetScriptLineNumberSafe(script, source_pos) + 1;
+ Script* script = Script::cast(maybe_script);
+ int line = script->GetLineNumber(source_pos) + 1;
Object* script_name_raw = script->name();
if (script_name_raw->IsString()) {
String* script_name = String::cast(script->name());
@@ -1171,7 +1170,7 @@
void JavaScriptFrame::Print(StringStream* accumulator,
PrintMode mode,
int index) const {
- HandleScope scope(isolate());
+ DisallowHeapAllocation no_gc;
Object* receiver = this->receiver();
JSFunction* function = this->function();
@@ -1185,13 +1184,11 @@
// doesn't contain scope info, scope_info will return 0 for the number of
// parameters, stack local variables, context local variables, stack slots,
// or context slots.
- Handle<ScopeInfo> scope_info(ScopeInfo::Empty(isolate()));
-
- Handle<SharedFunctionInfo> shared(function->shared());
- scope_info = Handle<ScopeInfo>(shared->scope_info());
+ SharedFunctionInfo* shared = function->shared();
+ ScopeInfo* scope_info = shared->scope_info();
Object* script_obj = shared->script();
if (script_obj->IsScript()) {
- Handle<Script> script(Script::cast(script_obj));
+ Script* script = Script::cast(script_obj);
accumulator->Add(" [");
accumulator->PrintName(script->name());
@@ -1199,11 +1196,11 @@
if (code != NULL && code->kind() == Code::FUNCTION &&
pc >= code->instruction_start() && pc < code->instruction_end()) {
int source_pos = code->SourcePosition(pc);
- int line = GetScriptLineNumberSafe(script, source_pos) + 1;
+ int line = script->GetLineNumber(source_pos) + 1;
accumulator->Add(":%d", line);
} else {
int function_start_pos = shared->start_position();
- int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
+ int line = script->GetLineNumber(function_start_pos) + 1;
accumulator->Add(":~%d", line);
}
diff --git a/src/full-codegen.h b/src/full-codegen.h
index 0d0a6ff..a6dcf5b 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -123,15 +123,20 @@
// Platform-specific code size multiplier.
#if V8_TARGET_ARCH_IA32
static const int kCodeSizeMultiplier = 100;
+ static const int kBootCodeSizeMultiplier = 100;
#elif V8_TARGET_ARCH_X64
static const int kCodeSizeMultiplier = 162;
+ static const int kBootCodeSizeMultiplier = 140;
#elif V8_TARGET_ARCH_ARM
static const int kCodeSizeMultiplier = 142;
+ static const int kBootCodeSizeMultiplier = 110;
#elif V8_TARGET_ARCH_ARM64
// TODO(all): Copied ARM value. Check this is sensible for ARM64.
static const int kCodeSizeMultiplier = 142;
+ static const int kBootCodeSizeMultiplier = 110;
#elif V8_TARGET_ARCH_MIPS
static const int kCodeSizeMultiplier = 142;
+ static const int kBootCodeSizeMultiplier = 120;
#else
#error Unsupported target architecture.
#endif
diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc
index 1af2784..ca08f3e 100644
--- a/src/gdb-jit.cc
+++ b/src/gdb-jit.cc
@@ -1002,7 +1002,7 @@
}
int GetScriptLineNumber(int pos) {
- return GetScriptLineNumberSafe(script_, pos) + 1;
+ return script_->GetLineNumber(pos) + 1;
}
@@ -2003,8 +2003,7 @@
CompilationInfo* info) {
if (!FLAG_gdbjit) return;
- // Force initialization of line_ends array.
- GetScriptLineNumber(script, 0);
+ Script::InitLineEnds(script);
if (!name.is_null() && name->IsString()) {
SmartArrayPointer<char> name_cstring =
diff --git a/src/globals.h b/src/globals.h
index db666d8..92401f6 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -78,7 +78,7 @@
#elif defined(__ARMEL__)
#define V8_HOST_ARCH_ARM 1
#define V8_HOST_ARCH_32_BIT 1
-#elif defined(__MIPSEL__)
+#elif defined(__MIPSEB__) || defined(__MIPSEL__)
#define V8_HOST_ARCH_MIPS 1
#define V8_HOST_ARCH_32_BIT 1
#else
@@ -108,7 +108,7 @@
#define V8_TARGET_ARCH_ARM64 1
#elif defined(__ARMEL__)
#define V8_TARGET_ARCH_ARM 1
-#elif defined(__MIPSEL__)
+#elif defined(__MIPSEB__) || defined(__MIPSEL__)
#define V8_TARGET_ARCH_MIPS 1
#else
#error Target architecture was not detected as supported by v8
@@ -147,7 +147,7 @@
#endif
#endif
-// Determine architecture endiannes (we only support little-endian).
+// Determine architecture endianness.
#if V8_TARGET_ARCH_IA32
#define V8_TARGET_LITTLE_ENDIAN 1
#elif V8_TARGET_ARCH_X64
@@ -157,9 +157,13 @@
#elif V8_TARGET_ARCH_ARM64
#define V8_TARGET_LITTLE_ENDIAN 1
#elif V8_TARGET_ARCH_MIPS
-#define V8_TARGET_LITTLE_ENDIAN 1
+#if defined(__MIPSEB__)
+#define V8_TARGET_BIG_ENDIAN 1
#else
-#error Unknown target architecture endiannes
+#define V8_TARGET_LITTLE_ENDIAN 1
+#endif
+#else
+#error Unknown target architecture endianness
#endif
// Determine whether the architecture uses an out-of-line constant pool.
diff --git a/src/handles.cc b/src/handles.cc
index a316cc0..f6dc0a9 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -27,19 +27,7 @@
#include "v8.h"
-#include "accessors.h"
-#include "api.h"
-#include "arguments.h"
-#include "bootstrapper.h"
-#include "compiler.h"
-#include "debug.h"
-#include "execution.h"
-#include "global-handles.h"
-#include "natives.h"
-#include "runtime.h"
-#include "string-search.h"
-#include "stub-cache.h"
-#include "vm-state-inl.h"
+#include "handles.h"
namespace v8 {
namespace internal {
@@ -124,532 +112,6 @@
}
-Handle<JSGlobalProxy> ReinitializeJSGlobalProxy(
- Handle<JSFunction> constructor,
- Handle<JSGlobalProxy> global) {
- CALL_HEAP_FUNCTION(
- constructor->GetIsolate(),
- constructor->GetHeap()->ReinitializeJSGlobalProxy(*constructor, *global),
- JSGlobalProxy);
-}
-
-
-MaybeHandle<Object> GetProperty(Handle<JSReceiver> obj,
- const char* name) {
- Isolate* isolate = obj->GetIsolate();
- Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
- ASSERT(!str.is_null());
- return Object::GetPropertyOrElement(obj, str);
-}
-
-
-// Wrappers for scripts are kept alive and cached in weak global
-// handles referred from foreign objects held by the scripts as long as
-// they are used. When they are not used anymore, the garbage
-// collector will call the weak callback on the global handle
-// associated with the wrapper and get rid of both the wrapper and the
-// handle.
-static void ClearWrapperCache(
- const v8::WeakCallbackData<v8::Value, void>& data) {
- Object** location = reinterpret_cast<Object**>(data.GetParameter());
- JSValue* wrapper = JSValue::cast(*location);
- Foreign* foreign = Script::cast(wrapper->value())->wrapper();
- ASSERT_EQ(foreign->foreign_address(), reinterpret_cast<Address>(location));
- foreign->set_foreign_address(0);
- GlobalHandles::Destroy(location);
- Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate());
- isolate->counters()->script_wrappers()->Decrement();
-}
-
-
-Handle<JSValue> GetScriptWrapper(Handle<Script> script) {
- if (script->wrapper()->foreign_address() != NULL) {
- // Return a handle for the existing script wrapper from the cache.
- return Handle<JSValue>(
- *reinterpret_cast<JSValue**>(script->wrapper()->foreign_address()));
- }
- Isolate* isolate = script->GetIsolate();
- // Construct a new script wrapper.
- isolate->counters()->script_wrappers()->Increment();
- Handle<JSFunction> constructor = isolate->script_function();
- Handle<JSValue> result =
- Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
-
- result->set_value(*script);
-
- // Create a new weak global handle and use it to cache the wrapper
- // for future use. The cache will automatically be cleared by the
- // garbage collector when it is not used anymore.
- Handle<Object> handle = isolate->global_handles()->Create(*result);
- GlobalHandles::MakeWeak(handle.location(),
- reinterpret_cast<void*>(handle.location()),
- &ClearWrapperCache);
- script->wrapper()->set_foreign_address(
- reinterpret_cast<Address>(handle.location()));
- return result;
-}
-
-
-// Init line_ends array with code positions of line ends inside script
-// source.
-void InitScriptLineEnds(Handle<Script> script) {
- if (!script->line_ends()->IsUndefined()) return;
-
- Isolate* isolate = script->GetIsolate();
-
- if (!script->source()->IsString()) {
- ASSERT(script->source()->IsUndefined());
- Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
- script->set_line_ends(*empty);
- ASSERT(script->line_ends()->IsFixedArray());
- return;
- }
-
- Handle<String> src(String::cast(script->source()), isolate);
-
- Handle<FixedArray> array = CalculateLineEnds(src, true);
-
- if (*array != isolate->heap()->empty_fixed_array()) {
- array->set_map(isolate->heap()->fixed_cow_array_map());
- }
-
- script->set_line_ends(*array);
- ASSERT(script->line_ends()->IsFixedArray());
-}
-
-
-template <typename SourceChar>
-static void CalculateLineEnds(Isolate* isolate,
- List<int>* line_ends,
- Vector<const SourceChar> src,
- bool with_last_line) {
- const int src_len = src.length();
- StringSearch<uint8_t, SourceChar> search(isolate, STATIC_ASCII_VECTOR("\n"));
-
- // Find and record line ends.
- int position = 0;
- while (position != -1 && position < src_len) {
- position = search.Search(src, position);
- if (position != -1) {
- line_ends->Add(position);
- position++;
- } else if (with_last_line) {
- // Even if the last line misses a line end, it is counted.
- line_ends->Add(src_len);
- return;
- }
- }
-}
-
-
-Handle<FixedArray> CalculateLineEnds(Handle<String> src,
- bool with_last_line) {
- src = String::Flatten(src);
- // Rough estimate of line count based on a roughly estimated average
- // length of (unpacked) code.
- int line_count_estimate = src->length() >> 4;
- List<int> line_ends(line_count_estimate);
- Isolate* isolate = src->GetIsolate();
- {
- DisallowHeapAllocation no_allocation; // ensure vectors stay valid.
- // Dispatch on type of strings.
- String::FlatContent content = src->GetFlatContent();
- ASSERT(content.IsFlat());
- if (content.IsAscii()) {
- CalculateLineEnds(isolate,
- &line_ends,
- content.ToOneByteVector(),
- with_last_line);
- } else {
- CalculateLineEnds(isolate,
- &line_ends,
- content.ToUC16Vector(),
- with_last_line);
- }
- }
- int line_count = line_ends.length();
- Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
- for (int i = 0; i < line_count; i++) {
- array->set(i, Smi::FromInt(line_ends[i]));
- }
- return array;
-}
-
-
-// Convert code position into line number.
-int GetScriptLineNumber(Handle<Script> script, int code_pos) {
- InitScriptLineEnds(script);
- DisallowHeapAllocation no_allocation;
- FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
- const int line_ends_len = line_ends_array->length();
-
- if (!line_ends_len) return -1;
-
- if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
- return script->line_offset()->value();
- }
-
- int left = 0;
- int right = line_ends_len;
- while (int half = (right - left) / 2) {
- if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
- right -= half;
- } else {
- left += half;
- }
- }
- return right + script->line_offset()->value();
-}
-
-
-// Convert code position into column number.
-int GetScriptColumnNumber(Handle<Script> script, int code_pos) {
- int line_number = GetScriptLineNumber(script, code_pos);
- if (line_number == -1) return -1;
-
- DisallowHeapAllocation no_allocation;
- FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
- line_number = line_number - script->line_offset()->value();
- if (line_number == 0) return code_pos + script->column_offset()->value();
- int prev_line_end_pos =
- Smi::cast(line_ends_array->get(line_number - 1))->value();
- return code_pos - (prev_line_end_pos + 1);
-}
-
-
-int GetScriptLineNumberSafe(Handle<Script> script, int code_pos) {
- DisallowHeapAllocation no_allocation;
- if (!script->line_ends()->IsUndefined()) {
- return GetScriptLineNumber(script, code_pos);
- }
- // Slow mode: we do not have line_ends. We have to iterate through source.
- if (!script->source()->IsString()) {
- return -1;
- }
- String* source = String::cast(script->source());
- int line = 0;
- int len = source->length();
- for (int pos = 0; pos < len; pos++) {
- if (pos == code_pos) {
- break;
- }
- if (source->Get(pos) == '\n') {
- line++;
- }
- }
- return line;
-}
-
-
-// Compute the property keys from the interceptor.
-// TODO(rossberg): support symbols in API, and filter here if needed.
-v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSReceiver> receiver,
- Handle<JSObject> object) {
- Isolate* isolate = receiver->GetIsolate();
- Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
- PropertyCallbackArguments
- args(isolate, interceptor->data(), *receiver, *object);
- v8::Handle<v8::Array> result;
- if (!interceptor->enumerator()->IsUndefined()) {
- v8::NamedPropertyEnumeratorCallback enum_fun =
- v8::ToCData<v8::NamedPropertyEnumeratorCallback>(
- interceptor->enumerator());
- LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
- result = args.Call(enum_fun);
- }
-#if ENABLE_EXTRA_CHECKS
- CHECK(result.IsEmpty() || v8::Utils::OpenHandle(*result)->IsJSObject());
-#endif
- return v8::Local<v8::Array>::New(reinterpret_cast<v8::Isolate*>(isolate),
- result);
-}
-
-
-// Compute the element keys from the interceptor.
-v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSReceiver> receiver,
- Handle<JSObject> object) {
- Isolate* isolate = receiver->GetIsolate();
- Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
- PropertyCallbackArguments
- args(isolate, interceptor->data(), *receiver, *object);
- v8::Handle<v8::Array> result;
- if (!interceptor->enumerator()->IsUndefined()) {
- v8::IndexedPropertyEnumeratorCallback enum_fun =
- v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
- interceptor->enumerator());
- LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
- result = args.Call(enum_fun);
-#if ENABLE_EXTRA_CHECKS
- CHECK(result.IsEmpty() || v8::Utils::OpenHandle(*result)->IsJSObject());
-#endif
- }
- return v8::Local<v8::Array>::New(reinterpret_cast<v8::Isolate*>(isolate),
- result);
-}
-
-
-Handle<Object> GetScriptNameOrSourceURL(Handle<Script> script) {
- Isolate* isolate = script->GetIsolate();
- Handle<String> name_or_source_url_key =
- isolate->factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("nameOrSourceURL"));
- Handle<JSValue> script_wrapper = GetScriptWrapper(script);
- Handle<Object> property = Object::GetProperty(
- script_wrapper, name_or_source_url_key).ToHandleChecked();
- ASSERT(property->IsJSFunction());
- Handle<JSFunction> method = Handle<JSFunction>::cast(property);
- Handle<Object> result;
- // Do not check against pending exception, since this function may be called
- // when an exception has already been pending.
- if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
- return isolate->factory()->undefined_value();
- }
- return result;
-}
-
-
-static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
- int len = array->length();
- for (int i = 0; i < len; i++) {
- Object* e = array->get(i);
- if (!(e->IsString() || e->IsNumber())) return false;
- }
- return true;
-}
-
-
-MaybeHandle<FixedArray> GetKeysInFixedArrayFor(Handle<JSReceiver> object,
- KeyCollectionType type) {
- USE(ContainsOnlyValidKeys);
- Isolate* isolate = object->GetIsolate();
- Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
- Handle<JSObject> arguments_boilerplate = Handle<JSObject>(
- isolate->context()->native_context()->sloppy_arguments_boilerplate(),
- isolate);
- Handle<JSFunction> arguments_function = Handle<JSFunction>(
- JSFunction::cast(arguments_boilerplate->map()->constructor()),
- isolate);
-
- // Only collect keys if access is permitted.
- for (Handle<Object> p = object;
- *p != isolate->heap()->null_value();
- p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
- if (p->IsJSProxy()) {
- Handle<JSProxy> proxy(JSProxy::cast(*p), isolate);
- Handle<Object> args[] = { proxy };
- Handle<Object> names;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, names,
- Execution::Call(isolate,
- isolate->proxy_enumerate(),
- object,
- ARRAY_SIZE(args),
- args),
- FixedArray);
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, content,
- FixedArray::AddKeysFromJSArray(
- content, Handle<JSArray>::cast(names)),
- FixedArray);
- break;
- }
-
- Handle<JSObject> current(JSObject::cast(*p), isolate);
-
- // Check access rights if required.
- if (current->IsAccessCheckNeeded() &&
- !isolate->MayNamedAccess(
- current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
- isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS);
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
- break;
- }
-
- // Compute the element keys.
- Handle<FixedArray> element_keys =
- isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
- current->GetEnumElementKeys(*element_keys);
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, content,
- FixedArray::UnionOfKeys(content, element_keys),
- FixedArray);
- ASSERT(ContainsOnlyValidKeys(content));
-
- // Add the element keys from the interceptor.
- if (current->HasIndexedInterceptor()) {
- v8::Handle<v8::Array> result =
- GetKeysForIndexedInterceptor(object, current);
- if (!result.IsEmpty()) {
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, content,
- FixedArray::AddKeysFromJSArray(
- content, v8::Utils::OpenHandle(*result)),
- FixedArray);
- }
- ASSERT(ContainsOnlyValidKeys(content));
- }
-
- // We can cache the computed property keys if access checks are
- // not needed and no interceptors are involved.
- //
- // We do not use the cache if the object has elements and
- // therefore it does not make sense to cache the property names
- // for arguments objects. Arguments objects will always have
- // elements.
- // Wrapped strings have elements, but don't have an elements
- // array or dictionary. So the fast inline test for whether to
- // use the cache says yes, so we should not create a cache.
- bool cache_enum_keys =
- ((current->map()->constructor() != *arguments_function) &&
- !current->IsJSValue() &&
- !current->IsAccessCheckNeeded() &&
- !current->HasNamedInterceptor() &&
- !current->HasIndexedInterceptor());
- // Compute the property keys and cache them if possible.
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, content,
- FixedArray::UnionOfKeys(
- content, GetEnumPropertyKeys(current, cache_enum_keys)),
- FixedArray);
- ASSERT(ContainsOnlyValidKeys(content));
-
- // Add the property keys from the interceptor.
- if (current->HasNamedInterceptor()) {
- v8::Handle<v8::Array> result =
- GetKeysForNamedInterceptor(object, current);
- if (!result.IsEmpty()) {
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, content,
- FixedArray::AddKeysFromJSArray(
- content, v8::Utils::OpenHandle(*result)),
- FixedArray);
- }
- ASSERT(ContainsOnlyValidKeys(content));
- }
-
- // If we only want local properties we bail out after the first
- // iteration.
- if (type == LOCAL_ONLY) break;
- }
- return content;
-}
-
-
-Handle<FixedArray> ReduceFixedArrayTo(Handle<FixedArray> array, int length) {
- ASSERT(array->length() >= length);
- if (array->length() == length) return array;
-
- Handle<FixedArray> new_array =
- array->GetIsolate()->factory()->NewFixedArray(length);
- for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
- return new_array;
-}
-
-
-Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
- bool cache_result) {
- Isolate* isolate = object->GetIsolate();
- if (object->HasFastProperties()) {
- int own_property_count = object->map()->EnumLength();
- // If the enum length of the given map is set to kInvalidEnumCache, this
- // means that the map itself has never used the present enum cache. The
- // first step to using the cache is to set the enum length of the map by
- // counting the number of own descriptors that are not DONT_ENUM or
- // SYMBOLIC.
- if (own_property_count == kInvalidEnumCacheSentinel) {
- own_property_count = object->map()->NumberOfDescribedProperties(
- OWN_DESCRIPTORS, DONT_SHOW);
- } else {
- ASSERT(own_property_count == object->map()->NumberOfDescribedProperties(
- OWN_DESCRIPTORS, DONT_SHOW));
- }
-
- if (object->map()->instance_descriptors()->HasEnumCache()) {
- DescriptorArray* desc = object->map()->instance_descriptors();
- Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
-
- // In case the number of properties required in the enum are actually
- // present, we can reuse the enum cache. Otherwise, this means that the
- // enum cache was generated for a previous (smaller) version of the
- // Descriptor Array. In that case we regenerate the enum cache.
- if (own_property_count <= keys->length()) {
- if (cache_result) object->map()->SetEnumLength(own_property_count);
- isolate->counters()->enum_cache_hits()->Increment();
- return ReduceFixedArrayTo(keys, own_property_count);
- }
- }
-
- Handle<Map> map(object->map());
-
- if (map->instance_descriptors()->IsEmpty()) {
- isolate->counters()->enum_cache_hits()->Increment();
- if (cache_result) map->SetEnumLength(0);
- return isolate->factory()->empty_fixed_array();
- }
-
- isolate->counters()->enum_cache_misses()->Increment();
-
- Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
- own_property_count);
- Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
- own_property_count);
-
- Handle<DescriptorArray> descs =
- Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
-
- int size = map->NumberOfOwnDescriptors();
- int index = 0;
-
- for (int i = 0; i < size; i++) {
- PropertyDetails details = descs->GetDetails(i);
- Object* key = descs->GetKey(i);
- if (!(details.IsDontEnum() || key->IsSymbol())) {
- storage->set(index, key);
- if (!indices.is_null()) {
- if (details.type() != FIELD) {
- indices = Handle<FixedArray>();
- } else {
- int field_index = descs->GetFieldIndex(i);
- if (field_index >= map->inobject_properties()) {
- field_index = -(field_index - map->inobject_properties() + 1);
- }
- field_index = field_index << 1;
- if (details.representation().IsDouble()) {
- field_index |= 1;
- }
- indices->set(index, Smi::FromInt(field_index));
- }
- }
- index++;
- }
- }
- ASSERT(index == storage->length());
-
- Handle<FixedArray> bridge_storage =
- isolate->factory()->NewFixedArray(
- DescriptorArray::kEnumCacheBridgeLength);
- DescriptorArray* desc = object->map()->instance_descriptors();
- desc->SetEnumCache(*bridge_storage,
- *storage,
- indices.is_null() ? Object::cast(Smi::FromInt(0))
- : Object::cast(*indices));
- if (cache_result) {
- object->map()->SetEnumLength(own_property_count);
- }
- return storage;
- } else {
- Handle<NameDictionary> dictionary(object->property_dictionary());
- int length = dictionary->NumberOfEnumElements();
- if (length == 0) {
- return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
- }
- Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
- dictionary->CopyEnumKeysTo(*storage);
- return storage;
- }
-}
-
-
DeferredHandleScope::DeferredHandleScope(Isolate* isolate)
: impl_(isolate->handle_scope_implementer()) {
impl_->BeginDeferredScope();
@@ -688,16 +150,4 @@
return deferred;
}
-
-void AddWeakObjectToCodeDependency(Heap* heap,
- Handle<Object> object,
- Handle<Code> code) {
- heap->EnsureWeakObjectToCodeTable();
- Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(*object));
- dep = DependentCode::Insert(dep, DependentCode::kWeakCodeGroup, code);
- CALL_HEAP_FUNCTION_VOID(heap->isolate(),
- heap->AddWeakObjectToCodeDependency(*object, *dep));
-}
-
-
} } // namespace v8::internal
diff --git a/src/handles.h b/src/handles.h
index b27394a..77534a4 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -28,7 +28,6 @@
#ifndef V8_HANDLES_H_
#define V8_HANDLES_H_
-#include "allocation.h"
#include "objects.h"
namespace v8 {
@@ -281,57 +280,6 @@
};
-// ----------------------------------------------------------------------------
-// Handle operations.
-// They might invoke garbage collection. The result is an handle to
-// an object of expected type, or the handle is an error if running out
-// of space or encountering an internal error.
-
-MUST_USE_RESULT MaybeHandle<Object> GetProperty(Handle<JSReceiver> obj,
- const char* name);
-
-// Get the JS object corresponding to the given script; create it
-// if none exists.
-Handle<JSValue> GetScriptWrapper(Handle<Script> script);
-
-// Script line number computations. Note that the line number is zero-based.
-void InitScriptLineEnds(Handle<Script> script);
-// For string calculates an array of line end positions. If the string
-// does not end with a new line character, this character may optionally be
-// imagined.
-Handle<FixedArray> CalculateLineEnds(Handle<String> string,
- bool with_imaginary_last_new_line);
-int GetScriptLineNumber(Handle<Script> script, int code_position);
-// The safe version does not make heap allocations but may work much slower.
-int GetScriptLineNumberSafe(Handle<Script> script, int code_position);
-int GetScriptColumnNumber(Handle<Script> script, int code_position);
-Handle<Object> GetScriptNameOrSourceURL(Handle<Script> script);
-
-// Computes the enumerable keys from interceptors. Used for debug mirrors and
-// by GetKeysInFixedArrayFor below.
-v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSReceiver> receiver,
- Handle<JSObject> object);
-v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSReceiver> receiver,
- Handle<JSObject> object);
-
-enum KeyCollectionType { LOCAL_ONLY, INCLUDE_PROTOS };
-
-// Computes the enumerable keys for a JSObject. Used for implementing
-// "for (n in object) { }".
-MUST_USE_RESULT MaybeHandle<FixedArray> GetKeysInFixedArrayFor(
- Handle<JSReceiver> object, KeyCollectionType type);
-Handle<FixedArray> ReduceFixedArrayTo(Handle<FixedArray> array, int length);
-Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
- bool cache_result);
-
-Handle<JSGlobalProxy> ReinitializeJSGlobalProxy(
- Handle<JSFunction> constructor,
- Handle<JSGlobalProxy> global);
-
-void AddWeakObjectToCodeDependency(Heap* heap,
- Handle<Object> object,
- Handle<Code> code);
-
// Seal off the current HandleScope so that new handles can only be created
// if a new HandleScope is entered.
class SealHandleScope BASE_EMBEDDED {
diff --git a/src/hashmap.h b/src/hashmap.h
index 11f6ace..65ca7a5 100644
--- a/src/hashmap.h
+++ b/src/hashmap.h
@@ -98,6 +98,11 @@
Entry* Start() const;
Entry* Next(Entry* p) const;
+ // Some match functions defined for convenience.
+ static bool PointersMatch(void* key1, void* key2) {
+ return key1 == key2;
+ }
+
private:
MatchFun match_;
Entry* map_;
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 8c94013..92222e3 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -85,22 +85,6 @@
}
-MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> str,
- PretenureFlag pretenure) {
- // Check for ASCII first since this is the common case.
- const char* start = str.start();
- int length = str.length();
- int non_ascii_start = String::NonAsciiStart(start, length);
- if (non_ascii_start >= length) {
- // If the string is ASCII, we do not need to convert the characters
- // since UTF8 is backwards compatible with ASCII.
- return AllocateStringFromOneByte(str, pretenure);
- }
- // Non-ASCII and we need to decode.
- return AllocateStringFromUtf8Slow(str, non_ascii_start, pretenure);
-}
-
-
template<>
bool inline Heap::IsOneByte(Vector<const char> str, int chars) {
// TODO(dcarney): incorporate Latin-1 check when Latin-1 is supported?
@@ -269,14 +253,6 @@
}
-MaybeObject* Heap::NumberFromInt32(
- int32_t value, PretenureFlag pretenure) {
- if (Smi::IsValid(value)) return Smi::FromInt(value);
- // Bypass NumberFromDouble to avoid various redundant checks.
- return AllocateHeapNumber(FastI2D(value), pretenure);
-}
-
-
MaybeObject* Heap::NumberFromUint32(
uint32_t value, PretenureFlag pretenure) {
if (static_cast<int32_t>(value) >= 0 &&
@@ -633,29 +609,34 @@
// Warning: Do not use the identifiers __object__, __maybe_object__ or
// __scope__ in a call to this macro.
+#define RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \
+ if (__maybe_object__->ToObject(&__object__)) { \
+ if (__object__ == (ISOLATE)->heap()->exception()) { RETURN_EMPTY; } \
+ RETURN_VALUE; \
+ }
+
#define CALL_AND_RETRY(ISOLATE, FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY) \
do { \
MaybeObject* __maybe_object__ = FUNCTION_CALL; \
Object* __object__ = NULL; \
- if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \
- if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY; \
+ RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \
+ ASSERT(__maybe_object__->IsRetryAfterGC()); \
(ISOLATE)->heap()->CollectGarbage(Failure::cast(__maybe_object__)-> \
allocation_space(), \
"allocation failure"); \
__maybe_object__ = FUNCTION_CALL; \
- if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \
- if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY; \
+ RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \
+ ASSERT(__maybe_object__->IsRetryAfterGC()); \
(ISOLATE)->counters()->gc_last_resort_from_handles()->Increment(); \
(ISOLATE)->heap()->CollectAllAvailableGarbage("last resort gc"); \
{ \
AlwaysAllocateScope __scope__(ISOLATE); \
__maybe_object__ = FUNCTION_CALL; \
} \
- if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \
- if (__maybe_object__->IsRetryAfterGC()) { \
+ RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \
+ ASSERT(__maybe_object__->IsRetryAfterGC()); \
/* TODO(1181417): Fix this. */ \
- v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true);\
- } \
+ v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); \
RETURN_EMPTY; \
} while (false)
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index 0f3e6ad..5253962 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -732,7 +732,7 @@
HeapEntriesMap::HeapEntriesMap()
- : entries_(HeapThingsMatch) {
+ : entries_(HashMap::PointersMatch) {
}
@@ -751,7 +751,7 @@
HeapObjectsSet::HeapObjectsSet()
- : entries_(HeapEntriesMap::HeapThingsMatch) {
+ : entries_(HashMap::PointersMatch) {
}
@@ -1081,7 +1081,9 @@
Address field = obj->address() + offset;
ASSERT(!Memory::Object_at(field)->IsFailure());
ASSERT(Memory::Object_at(field)->IsHeapObject());
- *field |= kFailureTag;
+ Object* untagged = *reinterpret_cast<Object**>(field);
+ intptr_t tagged = reinterpret_cast<intptr_t>(untagged) | kFailureTag;
+ *reinterpret_cast<Object**>(field) = reinterpret_cast<Object*>(tagged);
}
private:
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index 1582b2e..b34658d 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -315,9 +315,6 @@
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)),
v8::internal::kZeroHashSeed);
}
- static bool HeapThingsMatch(HeapThing key1, HeapThing key2) {
- return key1 == key2;
- }
HashMap entries_;
diff --git a/src/heap.cc b/src/heap.cc
index 8559cb4..5713537 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -81,6 +81,7 @@
// Will be 4 * reserved_semispace_size_ to ensure that young
// generation can be aligned to its size.
maximum_committed_(0),
+ old_space_growing_factor_(4),
survived_since_last_expansion_(0),
sweep_generation_(0),
always_allocate_scope_depth_(0),
@@ -2408,14 +2409,19 @@
}
-MaybeObject* Heap::AllocateCodeCache() {
- CodeCache* code_cache;
- { MaybeObject* maybe_code_cache = AllocateStruct(CODE_CACHE_TYPE);
- if (!maybe_code_cache->To(&code_cache)) return maybe_code_cache;
+MaybeObject* Heap::AllocateFillerObject(int size,
+ bool double_align,
+ AllocationSpace space) {
+ HeapObject* allocation;
+ { MaybeObject* maybe_allocation = AllocateRaw(size, space, space);
+ if (!maybe_allocation->To(&allocation)) return maybe_allocation;
}
- code_cache->set_default_cache(empty_fixed_array(), SKIP_WRITE_BARRIER);
- code_cache->set_normal_type_cache(undefined_value(), SKIP_WRITE_BARRIER);
- return code_cache;
+#ifdef DEBUG
+ MemoryChunk* chunk = MemoryChunk::FromAddress(allocation->address());
+ ASSERT(chunk->owner()->identity() == space);
+#endif
+ CreateFillerObjectAt(allocation->address(), size);
+ return allocation;
}
@@ -2424,16 +2430,6 @@
}
-MaybeObject* Heap::AllocateAliasedArgumentsEntry(int aliased_context_slot) {
- AliasedArgumentsEntry* entry;
- { MaybeObject* maybe_entry = AllocateStruct(ALIASED_ARGUMENTS_ENTRY_TYPE);
- if (!maybe_entry->To(&entry)) return maybe_entry;
- }
- entry->set_aliased_context_slot(aliased_context_slot);
- return entry;
-}
-
-
const Heap::StringTypeTable Heap::string_type_table[] = {
#define STRING_TYPE_ELEMENT(type, size, name, camel_name) \
{type, size, k##camel_name##MapRootIndex},
@@ -2503,6 +2499,9 @@
Oddball::cast(obj)->set_kind(Oddball::kUndefined);
ASSERT(!InNewSpace(undefined_value()));
+ // Set preliminary exception sentinel value before actually initializing it.
+ set_exception(null_value());
+
// Allocate the empty descriptor array.
{ MaybeObject* maybe_obj = AllocateEmptyFixedArray();
if (!maybe_obj->ToObject(&obj)) return false;
@@ -2582,6 +2581,7 @@
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, uninitialized);
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, arguments_marker);
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, no_interceptor_result_sentinel);
+ ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, exception);
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, termination_exception);
for (unsigned i = 0; i < ARRAY_SIZE(string_type_table); i++) {
@@ -2589,7 +2589,11 @@
{ MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size);
if (!maybe_obj->ToObject(&obj)) return false;
}
- roots_[entry.index] = Map::cast(obj);
+ // Mark cons string maps as unstable, because their objects can change
+ // maps during GC.
+ Map* map = Map::cast(obj);
+ if (StringShape(entry.type).IsCons()) map->mark_unstable();
+ roots_[entry.index] = map;
}
ALLOCATE_VARSIZE_MAP(STRING_TYPE, undetectable_string)
@@ -2745,32 +2749,6 @@
}
-MaybeObject* Heap::AllocateAllocationSite() {
- AllocationSite* site;
- MaybeObject* maybe_result = Allocate(allocation_site_map(),
- OLD_POINTER_SPACE);
- if (!maybe_result->To(&site)) return maybe_result;
- site->Initialize();
-
- // Link the site
- site->set_weak_next(allocation_sites_list());
- set_allocation_sites_list(site);
- return site;
-}
-
-
-MaybeObject* Heap::CreateOddball(Map* map,
- const char* to_string,
- Object* to_number,
- byte kind) {
- Object* result;
- { MaybeObject* maybe_result = Allocate(map, OLD_POINTER_SPACE);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- return Oddball::cast(result)->Initialize(this, to_string, to_number, kind);
-}
-
-
bool Heap::CreateApiObjects() {
Object* obj;
@@ -2843,116 +2821,89 @@
bool Heap::CreateInitialObjects() {
- Object* obj;
+ HandleScope scope(isolate());
+ Factory* factory = isolate()->factory();
// The -0 value must be set before NumberFromDouble works.
- { MaybeObject* maybe_obj = AllocateHeapNumber(-0.0, TENURED);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_minus_zero_value(HeapNumber::cast(obj));
+ set_minus_zero_value(*factory->NewHeapNumber(-0.0, TENURED));
ASSERT(std::signbit(minus_zero_value()->Number()) != 0);
- { MaybeObject* maybe_obj = AllocateHeapNumber(OS::nan_value(), TENURED);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_nan_value(HeapNumber::cast(obj));
-
- { MaybeObject* maybe_obj = AllocateHeapNumber(V8_INFINITY, TENURED);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_infinity_value(HeapNumber::cast(obj));
+ set_nan_value(*factory->NewHeapNumber(OS::nan_value(), TENURED));
+ set_infinity_value(*factory->NewHeapNumber(V8_INFINITY, TENURED));
// The hole has not been created yet, but we want to put something
// predictable in the gaps in the string table, so lets make that Smi zero.
set_the_hole_value(reinterpret_cast<Oddball*>(Smi::FromInt(0)));
// Allocate initial string table.
- { MaybeObject* maybe_obj =
- StringTable::Allocate(this, kInitialStringTableSize);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- // Don't use set_string_table() due to asserts.
- roots_[kStringTableRootIndex] = obj;
+ set_string_table(*StringTable::New(isolate(), kInitialStringTableSize));
// Finish initializing oddballs after creating the string table.
- { MaybeObject* maybe_obj =
- undefined_value()->Initialize(this,
- "undefined",
- nan_value(),
- Oddball::kUndefined);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
+ Oddball::Initialize(isolate(),
+ factory->undefined_value(),
+ "undefined",
+ factory->nan_value(),
+ Oddball::kUndefined);
// Initialize the null_value.
- { MaybeObject* maybe_obj = null_value()->Initialize(
- this, "null", Smi::FromInt(0), Oddball::kNull);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
+ Oddball::Initialize(isolate(),
+ factory->null_value(),
+ "null",
+ handle(Smi::FromInt(0), isolate()),
+ Oddball::kNull);
- { MaybeObject* maybe_obj = CreateOddball(boolean_map(),
- "true",
- Smi::FromInt(1),
- Oddball::kTrue);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_true_value(Oddball::cast(obj));
+ set_true_value(*factory->NewOddball(factory->boolean_map(),
+ "true",
+ handle(Smi::FromInt(1), isolate()),
+ Oddball::kTrue));
- { MaybeObject* maybe_obj = CreateOddball(boolean_map(),
- "false",
- Smi::FromInt(0),
- Oddball::kFalse);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_false_value(Oddball::cast(obj));
+ set_false_value(*factory->NewOddball(factory->boolean_map(),
+ "false",
+ handle(Smi::FromInt(0), isolate()),
+ Oddball::kFalse));
- { MaybeObject* maybe_obj = CreateOddball(the_hole_map(),
- "hole",
- Smi::FromInt(-1),
- Oddball::kTheHole);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_the_hole_value(Oddball::cast(obj));
+ set_the_hole_value(*factory->NewOddball(factory->the_hole_map(),
+ "hole",
+ handle(Smi::FromInt(-1), isolate()),
+ Oddball::kTheHole));
- { MaybeObject* maybe_obj = CreateOddball(uninitialized_map(),
- "uninitialized",
- Smi::FromInt(-1),
- Oddball::kUninitialized);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_uninitialized_value(Oddball::cast(obj));
+ set_uninitialized_value(
+ *factory->NewOddball(factory->uninitialized_map(),
+ "uninitialized",
+ handle(Smi::FromInt(-1), isolate()),
+ Oddball::kUninitialized));
- { MaybeObject* maybe_obj = CreateOddball(arguments_marker_map(),
- "arguments_marker",
- Smi::FromInt(-4),
- Oddball::kArgumentMarker);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_arguments_marker(Oddball::cast(obj));
+ set_arguments_marker(*factory->NewOddball(factory->arguments_marker_map(),
+ "arguments_marker",
+ handle(Smi::FromInt(-4), isolate()),
+ Oddball::kArgumentMarker));
- { MaybeObject* maybe_obj = CreateOddball(no_interceptor_result_sentinel_map(),
- "no_interceptor_result_sentinel",
- Smi::FromInt(-2),
- Oddball::kOther);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_no_interceptor_result_sentinel(Oddball::cast(obj));
+ set_no_interceptor_result_sentinel(
+ *factory->NewOddball(factory->no_interceptor_result_sentinel_map(),
+ "no_interceptor_result_sentinel",
+ handle(Smi::FromInt(-2), isolate()),
+ Oddball::kOther));
- { MaybeObject* maybe_obj = CreateOddball(termination_exception_map(),
- "termination_exception",
- Smi::FromInt(-3),
- Oddball::kOther);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- set_termination_exception(Oddball::cast(obj));
+ set_termination_exception(
+ *factory->NewOddball(factory->termination_exception_map(),
+ "termination_exception",
+ handle(Smi::FromInt(-3), isolate()),
+ Oddball::kOther));
+
+ set_exception(
+ *factory->NewOddball(factory->exception_map(),
+ "exception",
+ handle(Smi::FromInt(-5), isolate()),
+ Oddball::kException));
for (unsigned i = 0; i < ARRAY_SIZE(constant_string_table); i++) {
- { MaybeObject* maybe_obj =
- InternalizeUtf8String(constant_string_table[i].contents);
- if (!maybe_obj->ToObject(&obj)) return false;
- }
- roots_[constant_string_table[i].index] = String::cast(obj);
+ Handle<String> str =
+ factory->InternalizeUtf8String(constant_string_table[i].contents);
+ roots_[constant_string_table[i].index] = *str;
}
+ Object* obj;
+
// Allocate the hidden string which is used to identify the hidden properties
// in JSObjects. The hash code has a special value so that it will not match
// the empty string when searching for the property. It cannot be part of the
@@ -2992,11 +2943,12 @@
CreateFixedStubs();
// Allocate the dictionary of intrinsic function names.
- { MaybeObject* maybe_obj =
- NameDictionary::Allocate(this, Runtime::kNumFunctions);
- if (!maybe_obj->ToObject(&obj)) return false;
+ {
+ Handle<NameDictionary> function_names =
+ NameDictionary::New(isolate(), Runtime::kNumFunctions);
+ Runtime::InitializeIntrinsicFunctionNames(isolate(), function_names);
+ set_intrinsic_function_names(*function_names);
}
- set_intrinsic_function_names(NameDictionary::cast(obj));
{ MaybeObject* maybe_obj = AllocateInitialNumberStringCache();
if (!maybe_obj->ToObject(&obj)) return false;
@@ -3195,60 +3147,58 @@
}
-void RegExpResultsCache::Enter(Heap* heap,
- String* key_string,
- Object* key_pattern,
- FixedArray* value_array,
+void RegExpResultsCache::Enter(Isolate* isolate,
+ Handle<String> key_string,
+ Handle<Object> key_pattern,
+ Handle<FixedArray> value_array,
ResultsCacheType type) {
- FixedArray* cache;
+ Factory* factory = isolate->factory();
+ Handle<FixedArray> cache;
if (!key_string->IsInternalizedString()) return;
if (type == STRING_SPLIT_SUBSTRINGS) {
ASSERT(key_pattern->IsString());
if (!key_pattern->IsInternalizedString()) return;
- cache = heap->string_split_cache();
+ cache = factory->string_split_cache();
} else {
ASSERT(type == REGEXP_MULTIPLE_INDICES);
ASSERT(key_pattern->IsFixedArray());
- cache = heap->regexp_multiple_cache();
+ cache = factory->regexp_multiple_cache();
}
uint32_t hash = key_string->Hash();
uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) &
~(kArrayEntriesPerCacheEntry - 1));
if (cache->get(index + kStringOffset) == Smi::FromInt(0)) {
- cache->set(index + kStringOffset, key_string);
- cache->set(index + kPatternOffset, key_pattern);
- cache->set(index + kArrayOffset, value_array);
+ cache->set(index + kStringOffset, *key_string);
+ cache->set(index + kPatternOffset, *key_pattern);
+ cache->set(index + kArrayOffset, *value_array);
} else {
uint32_t index2 =
((index + kArrayEntriesPerCacheEntry) & (kRegExpResultsCacheSize - 1));
if (cache->get(index2 + kStringOffset) == Smi::FromInt(0)) {
- cache->set(index2 + kStringOffset, key_string);
- cache->set(index2 + kPatternOffset, key_pattern);
- cache->set(index2 + kArrayOffset, value_array);
+ cache->set(index2 + kStringOffset, *key_string);
+ cache->set(index2 + kPatternOffset, *key_pattern);
+ cache->set(index2 + kArrayOffset, *value_array);
} else {
cache->set(index2 + kStringOffset, Smi::FromInt(0));
cache->set(index2 + kPatternOffset, Smi::FromInt(0));
cache->set(index2 + kArrayOffset, Smi::FromInt(0));
- cache->set(index + kStringOffset, key_string);
- cache->set(index + kPatternOffset, key_pattern);
- cache->set(index + kArrayOffset, value_array);
+ cache->set(index + kStringOffset, *key_string);
+ cache->set(index + kPatternOffset, *key_pattern);
+ cache->set(index + kArrayOffset, *value_array);
}
}
// If the array is a reasonably short list of substrings, convert it into a
// list of internalized strings.
if (type == STRING_SPLIT_SUBSTRINGS && value_array->length() < 100) {
for (int i = 0; i < value_array->length(); i++) {
- String* str = String::cast(value_array->get(i));
- Object* internalized_str;
- MaybeObject* maybe_string = heap->InternalizeString(str);
- if (maybe_string->ToObject(&internalized_str)) {
- value_array->set(i, internalized_str);
- }
+ Handle<String> str(String::cast(value_array->get(i)), isolate);
+ Handle<String> internalized_str = factory->InternalizeString(str);
+ value_array->set(i, *internalized_str);
}
}
// Convert backing store to a copy-on-write array.
- value_array->set_map_no_write_barrier(heap->fixed_cow_array_map());
+ value_array->set_map_no_write_barrier(*factory->fixed_cow_array_map());
}
@@ -3279,24 +3229,6 @@
}
-void Heap::AllocateFullSizeNumberStringCache() {
- // The idea is to have a small number string 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() || FLAG_extra_code != NULL);
- MaybeObject* maybe_obj =
- AllocateFixedArray(FullSizeNumberStringCacheLength(), TENURED);
- Object* new_cache;
- if (maybe_obj->ToObject(&new_cache)) {
- // We don't bother to repopulate the cache with entries from the old cache.
- // It will be repopulated soon enough with new strings.
- set_number_string_cache(FixedArray::cast(new_cache));
- }
- // If allocation fails then we just return without doing anything. It is only
- // a cache, so best effort is OK here.
-}
-
-
void Heap::FlushNumberStringCache() {
// Flush the number to string cache.
int len = number_string_cache()->length();
@@ -3306,100 +3238,6 @@
}
-static inline int double_get_hash(double d) {
- DoubleRepresentation rep(d);
- return static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32);
-}
-
-
-static inline int smi_get_hash(Smi* smi) {
- return smi->value();
-}
-
-
-Object* Heap::GetNumberStringCache(Object* number) {
- int hash;
- int mask = (number_string_cache()->length() >> 1) - 1;
- if (number->IsSmi()) {
- hash = smi_get_hash(Smi::cast(number)) & mask;
- } else {
- hash = double_get_hash(number->Number()) & mask;
- }
- Object* key = number_string_cache()->get(hash * 2);
- if (key == number) {
- return String::cast(number_string_cache()->get(hash * 2 + 1));
- } else if (key->IsHeapNumber() &&
- number->IsHeapNumber() &&
- key->Number() == number->Number()) {
- return String::cast(number_string_cache()->get(hash * 2 + 1));
- }
- return undefined_value();
-}
-
-
-void Heap::SetNumberStringCache(Object* number, String* string) {
- int hash;
- int mask = (number_string_cache()->length() >> 1) - 1;
- if (number->IsSmi()) {
- hash = smi_get_hash(Smi::cast(number)) & mask;
- } else {
- hash = double_get_hash(number->Number()) & mask;
- }
- if (number_string_cache()->get(hash * 2) != undefined_value() &&
- number_string_cache()->length() != FullSizeNumberStringCacheLength()) {
- // The first time we have a hash collision, we move to the full sized
- // number string cache.
- AllocateFullSizeNumberStringCache();
- return;
- }
- number_string_cache()->set(hash * 2, number);
- number_string_cache()->set(hash * 2 + 1, string);
-}
-
-
-MaybeObject* Heap::NumberToString(Object* number,
- bool check_number_string_cache) {
- isolate_->counters()->number_to_string_runtime()->Increment();
- if (check_number_string_cache) {
- Object* cached = GetNumberStringCache(number);
- if (cached != undefined_value()) {
- return cached;
- }
- }
-
- char arr[100];
- Vector<char> buffer(arr, ARRAY_SIZE(arr));
- const char* str;
- if (number->IsSmi()) {
- int num = Smi::cast(number)->value();
- str = IntToCString(num, buffer);
- } else {
- double num = HeapNumber::cast(number)->value();
- str = DoubleToCString(num, buffer);
- }
-
- Object* js_string;
-
- // We tenure the allocated string since it is referenced from the
- // number-string cache which lives in the old space.
- MaybeObject* maybe_js_string =
- AllocateStringFromOneByte(CStrVector(str), TENURED);
- if (maybe_js_string->ToObject(&js_string)) {
- SetNumberStringCache(number, String::cast(js_string));
- }
- return maybe_js_string;
-}
-
-
-MaybeObject* Heap::Uint32ToString(uint32_t value,
- bool check_number_string_cache) {
- Object* number;
- MaybeObject* maybe = NumberFromUint32(value);
- if (!maybe->To<Object>(&number)) return maybe;
- return NumberToString(number, check_number_string_cache);
-}
-
-
MaybeObject* Heap::AllocateAllocationSitesScratchpad() {
MaybeObject* maybe_obj =
AllocateFixedArray(kAllocationSiteScratchpadSize, TENURED);
@@ -3537,24 +3375,6 @@
}
-MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) {
- // We need to distinguish the minus zero value and this cannot be
- // done after conversion to int. Doing this by comparing bit
- // patterns is faster than using fpclassify() et al.
- if (IsMinusZero(value)) {
- return AllocateHeapNumber(-0.0, pretenure);
- }
-
- int int_value = FastD2I(value);
- if (value == int_value && Smi::IsValid(int_value)) {
- return Smi::FromInt(int_value);
- }
-
- // Materialize the value in the heap.
- return AllocateHeapNumber(value, pretenure);
-}
-
-
MaybeObject* Heap::AllocateForeign(Address address, PretenureFlag pretenure) {
// Statically ensure that it is safe to allocate foreigns in paged spaces.
STATIC_ASSERT(Foreign::kSize <= Page::kMaxRegularHeapObjectSize);
@@ -3567,119 +3387,6 @@
}
-MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
- SharedFunctionInfo* share;
- MaybeObject* maybe = Allocate(shared_function_info_map(), OLD_POINTER_SPACE);
- if (!maybe->To<SharedFunctionInfo>(&share)) return maybe;
-
- // Set pointer fields.
- share->set_name(name);
- Code* illegal = isolate_->builtins()->builtin(Builtins::kIllegal);
- share->set_code(illegal);
- share->set_optimized_code_map(Smi::FromInt(0));
- share->set_scope_info(ScopeInfo::Empty(isolate_));
- Code* construct_stub =
- isolate_->builtins()->builtin(Builtins::kJSConstructStubGeneric);
- share->set_construct_stub(construct_stub);
- share->set_instance_class_name(Object_string());
- share->set_function_data(undefined_value(), SKIP_WRITE_BARRIER);
- share->set_script(undefined_value(), SKIP_WRITE_BARRIER);
- share->set_debug_info(undefined_value(), SKIP_WRITE_BARRIER);
- share->set_inferred_name(empty_string(), SKIP_WRITE_BARRIER);
- share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER);
- share->set_ast_node_count(0);
- share->set_counters(0);
-
- // Set integer fields (smi or int, depending on the architecture).
- share->set_length(0);
- share->set_formal_parameter_count(0);
- share->set_expected_nof_properties(0);
- share->set_num_literals(0);
- share->set_start_position_and_type(0);
- share->set_end_position(0);
- share->set_function_token_position(0);
- // All compiler hints default to false or 0.
- share->set_compiler_hints(0);
- share->set_opt_count_and_bailout_reason(0);
-
- return share;
-}
-
-
-MaybeObject* Heap::AllocateJSMessageObject(String* type,
- JSArray* arguments,
- int start_position,
- int end_position,
- Object* script,
- Object* stack_frames) {
- Object* result;
- { MaybeObject* maybe_result = Allocate(message_object_map(), NEW_SPACE);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- JSMessageObject* message = JSMessageObject::cast(result);
- message->set_properties(Heap::empty_fixed_array(), SKIP_WRITE_BARRIER);
- message->initialize_elements();
- message->set_elements(Heap::empty_fixed_array(), SKIP_WRITE_BARRIER);
- message->set_type(type);
- message->set_arguments(arguments);
- message->set_start_position(start_position);
- message->set_end_position(end_position);
- message->set_script(script);
- message->set_stack_frames(stack_frames);
- return result;
-}
-
-
-MaybeObject* Heap::AllocateExternalStringFromAscii(
- const ExternalAsciiString::Resource* resource) {
- size_t length = resource->length();
- if (length > static_cast<size_t>(String::kMaxLength)) {
- return isolate()->ThrowInvalidStringLength();
- }
-
- Map* map = external_ascii_string_map();
- Object* result;
- { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
-
- ExternalAsciiString* external_string = ExternalAsciiString::cast(result);
- external_string->set_length(static_cast<int>(length));
- external_string->set_hash_field(String::kEmptyHashField);
- external_string->set_resource(resource);
-
- return result;
-}
-
-
-MaybeObject* Heap::AllocateExternalStringFromTwoByte(
- const ExternalTwoByteString::Resource* resource) {
- size_t length = resource->length();
- if (length > static_cast<size_t>(String::kMaxLength)) {
- return isolate()->ThrowInvalidStringLength();
- }
-
- // For small strings we check whether the resource contains only
- // one byte characters. If yes, we use a different string map.
- static const size_t kOneByteCheckLengthLimit = 32;
- bool is_one_byte = length <= kOneByteCheckLengthLimit &&
- String::IsOneByte(resource->data(), static_cast<int>(length));
- Map* map = is_one_byte ?
- external_string_with_one_byte_data_map() : external_string_map();
- Object* result;
- { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
-
- ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result);
- external_string->set_length(static_cast<int>(length));
- external_string->set_hash_field(String::kEmptyHashField);
- external_string->set_resource(resource);
-
- return result;
-}
-
-
MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
if (code <= String::kMaxOneByteCharCode) {
Object* value = single_character_string_cache()->get(code);
@@ -3697,7 +3404,7 @@
}
SeqTwoByteString* result;
- { MaybeObject* maybe_result = AllocateRawTwoByteString(1);
+ { MaybeObject* maybe_result = AllocateRawTwoByteString(1, NOT_TENURED);
if (!maybe_result->To<SeqTwoByteString>(&result)) return maybe_result;
}
result->SeqTwoByteStringSet(0, code);
@@ -3837,107 +3544,37 @@
}
-MaybeObject* Heap::CreateCode(const CodeDesc& desc,
- Code::Flags flags,
- Handle<Object> self_reference,
- bool immovable,
- bool crankshafted,
- int prologue_offset) {
- // Allocate ByteArray and ConstantPoolArray before the Code object, so that we
- // do not risk leaving uninitialized Code object (and breaking the heap).
- ByteArray* reloc_info;
- MaybeObject* maybe_reloc_info = AllocateByteArray(desc.reloc_size, TENURED);
- if (!maybe_reloc_info->To(&reloc_info)) return maybe_reloc_info;
-
- ConstantPoolArray* constant_pool;
- if (FLAG_enable_ool_constant_pool) {
- MaybeObject* maybe_constant_pool = desc.origin->AllocateConstantPool(this);
- if (!maybe_constant_pool->To(&constant_pool)) return maybe_constant_pool;
- } else {
- constant_pool = empty_constant_pool_array();
- }
-
- // Compute size.
- int body_size = RoundUp(desc.instr_size, kObjectAlignment);
- int obj_size = Code::SizeFor(body_size);
- ASSERT(IsAligned(static_cast<intptr_t>(obj_size), kCodeAlignment));
+MaybeObject* Heap::AllocateCode(int object_size,
+ bool immovable) {
+ ASSERT(IsAligned(static_cast<intptr_t>(object_size), kCodeAlignment));
MaybeObject* maybe_result;
// Large code objects and code objects which should stay at a fixed address
// are allocated in large object space.
HeapObject* result;
- bool force_lo_space = obj_size > code_space()->AreaSize();
+ bool force_lo_space = object_size > code_space()->AreaSize();
if (force_lo_space) {
- maybe_result = lo_space_->AllocateRaw(obj_size, EXECUTABLE);
+ maybe_result = lo_space_->AllocateRaw(object_size, EXECUTABLE);
} else {
- maybe_result = AllocateRaw(obj_size, CODE_SPACE, CODE_SPACE);
+ maybe_result = AllocateRaw(object_size, CODE_SPACE, CODE_SPACE);
}
if (!maybe_result->To<HeapObject>(&result)) return maybe_result;
if (immovable && !force_lo_space &&
- // Objects on the first page of each space are never moved.
- !code_space_->FirstPage()->Contains(result->address())) {
+ // Objects on the first page of each space are never moved.
+ !code_space_->FirstPage()->Contains(result->address())) {
// Discard the first code allocation, which was on a page where it could be
// moved.
- CreateFillerObjectAt(result->address(), obj_size);
- maybe_result = lo_space_->AllocateRaw(obj_size, EXECUTABLE);
+ CreateFillerObjectAt(result->address(), object_size);
+ maybe_result = lo_space_->AllocateRaw(object_size, EXECUTABLE);
if (!maybe_result->To<HeapObject>(&result)) return maybe_result;
}
- // Initialize the object
result->set_map_no_write_barrier(code_map());
Code* code = Code::cast(result);
ASSERT(!isolate_->code_range()->exists() ||
isolate_->code_range()->contains(code->address()));
- code->set_instruction_size(desc.instr_size);
- code->set_relocation_info(reloc_info);
- code->set_flags(flags);
- code->set_raw_kind_specific_flags1(0);
- code->set_raw_kind_specific_flags2(0);
- code->set_is_crankshafted(crankshafted);
- code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER);
- code->set_raw_type_feedback_info(undefined_value());
- code->set_next_code_link(undefined_value());
- code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_gc_metadata(Smi::FromInt(0));
code->set_ic_age(global_ic_age_);
- code->set_prologue_offset(prologue_offset);
- if (code->kind() == Code::OPTIMIZED_FUNCTION) {
- ASSERT(!code->marked_for_deoptimization());
- }
- if (code->is_inline_cache_stub()) {
- ASSERT(!code->is_weak_stub());
- ASSERT(!code->is_invalidated_weak_stub());
- }
-
- if (FLAG_enable_ool_constant_pool) {
- desc.origin->PopulateConstantPool(constant_pool);
- }
- code->set_constant_pool(constant_pool);
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
- if (code->kind() == Code::FUNCTION) {
- code->set_has_debug_break_slots(
- isolate_->debugger()->IsDebuggerActive());
- }
-#endif
-
- // Allow self references to created code object by patching the handle to
- // point to the newly allocated Code object.
- if (!self_reference.is_null()) {
- *(self_reference.location()) = code;
- }
- // Migrate generated code.
- // The generated code can contain Object** values (typically from handles)
- // that are dereferenced during the copy to point directly to the actual heap
- // objects. These pointers can include references to the code object itself,
- // through the self_reference parameter.
- code->CopyFrom(desc);
-
-#ifdef VERIFY_HEAP
- if (FLAG_verify_heap) {
- code->Verify();
- }
-#endif
return code;
}
@@ -4093,36 +3730,6 @@
}
-void Heap::InitializeFunction(JSFunction* function,
- SharedFunctionInfo* shared,
- Object* prototype) {
- ASSERT(!prototype->IsMap());
- function->initialize_properties();
- function->initialize_elements();
- function->set_shared(shared);
- function->set_code(shared->code());
- function->set_prototype_or_initial_map(prototype);
- function->set_context(undefined_value());
- function->set_literals_or_bindings(empty_fixed_array());
- function->set_next_function_link(undefined_value());
-}
-
-
-MaybeObject* Heap::AllocateFunction(Map* function_map,
- SharedFunctionInfo* shared,
- Object* prototype,
- PretenureFlag pretenure) {
- AllocationSpace space =
- (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
- Object* result;
- { MaybeObject* maybe_result = Allocate(function_map, space);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- InitializeFunction(JSFunction::cast(result), shared, prototype);
- return result;
-}
-
-
MaybeObject* Heap::AllocateArgumentsObject(Object* callee, int length) {
// To get fast allocation and map sharing for arguments objects we
// allocate them based on an arguments boilerplate.
@@ -4271,52 +3878,6 @@
}
-MaybeObject* Heap::AllocateJSProxy(Object* handler, Object* prototype) {
- // Allocate map.
- // TODO(rossberg): Once we optimize proxies, think about a scheme to share
- // maps. Will probably depend on the identity of the handler object, too.
- Map* map;
- MaybeObject* maybe_map_obj = AllocateMap(JS_PROXY_TYPE, JSProxy::kSize);
- if (!maybe_map_obj->To<Map>(&map)) return maybe_map_obj;
- map->set_prototype(prototype);
-
- // Allocate the proxy object.
- JSProxy* result;
- MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
- if (!maybe_result->To<JSProxy>(&result)) return maybe_result;
- result->InitializeBody(map->instance_size(), Smi::FromInt(0));
- result->set_handler(handler);
- result->set_hash(undefined_value(), SKIP_WRITE_BARRIER);
- return result;
-}
-
-
-MaybeObject* Heap::AllocateJSFunctionProxy(Object* handler,
- Object* call_trap,
- Object* construct_trap,
- Object* prototype) {
- // Allocate map.
- // TODO(rossberg): Once we optimize proxies, think about a scheme to share
- // maps. Will probably depend on the identity of the handler object, too.
- Map* map;
- MaybeObject* maybe_map_obj =
- AllocateMap(JS_FUNCTION_PROXY_TYPE, JSFunctionProxy::kSize);
- if (!maybe_map_obj->To<Map>(&map)) return maybe_map_obj;
- map->set_prototype(prototype);
-
- // Allocate the proxy object.
- JSFunctionProxy* result;
- MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
- if (!maybe_result->To<JSFunctionProxy>(&result)) return maybe_result;
- result->InitializeBody(map->instance_size(), Smi::FromInt(0));
- result->set_handler(handler);
- result->set_hash(undefined_value(), SKIP_WRITE_BARRIER);
- result->set_call_trap(call_trap);
- result->set_construct_trap(construct_trap);
- return result;
-}
-
-
MaybeObject* Heap::CopyJSObject(JSObject* source, AllocationSite* site) {
// Never used to copy functions. If functions need to be copied we
// have to be careful to clear the literals array.
@@ -4402,114 +3963,6 @@
}
-MaybeObject* Heap::ReinitializeJSReceiver(
- JSReceiver* object, InstanceType type, int size) {
- ASSERT(type >= FIRST_JS_OBJECT_TYPE);
-
- // Allocate fresh map.
- // TODO(rossberg): Once we optimize proxies, cache these maps.
- Map* map;
- MaybeObject* maybe = AllocateMap(type, size);
- if (!maybe->To<Map>(&map)) return maybe;
-
- // Check that the receiver has at least the size of the fresh object.
- int size_difference = object->map()->instance_size() - map->instance_size();
- ASSERT(size_difference >= 0);
-
- map->set_prototype(object->map()->prototype());
-
- // Allocate the backing storage for the properties.
- int prop_size = map->unused_property_fields() - map->inobject_properties();
- Object* properties;
- maybe = AllocateFixedArray(prop_size, TENURED);
- if (!maybe->ToObject(&properties)) return maybe;
-
- // Functions require some allocation, which might fail here.
- SharedFunctionInfo* shared = NULL;
- if (type == JS_FUNCTION_TYPE) {
- String* name;
- OneByteStringKey key(STATIC_ASCII_VECTOR("<freezing call trap>"),
- HashSeed());
- maybe = InternalizeStringWithKey(&key);
- if (!maybe->To<String>(&name)) return maybe;
- maybe = AllocateSharedFunctionInfo(name);
- if (!maybe->To<SharedFunctionInfo>(&shared)) return maybe;
- }
-
- // Because of possible retries of this function after failure,
- // we must NOT fail after this point, where we have changed the type!
-
- // Reset the map for the object.
- object->set_map(map);
- JSObject* jsobj = JSObject::cast(object);
-
- // Reinitialize the object from the constructor map.
- InitializeJSObjectFromMap(jsobj, FixedArray::cast(properties), map);
-
- // Functions require some minimal initialization.
- if (type == JS_FUNCTION_TYPE) {
- map->set_function_with_prototype(true);
- InitializeFunction(JSFunction::cast(object), shared, the_hole_value());
- JSFunction::cast(object)->set_context(
- isolate()->context()->native_context());
- }
-
- // Put in filler if the new object is smaller than the old.
- if (size_difference > 0) {
- CreateFillerObjectAt(
- object->address() + map->instance_size(), size_difference);
- }
-
- return object;
-}
-
-
-MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor,
- JSGlobalProxy* object) {
- ASSERT(constructor->has_initial_map());
- Map* map = constructor->initial_map();
-
- // Check that the already allocated object has the same size and type as
- // objects allocated using the constructor.
- ASSERT(map->instance_size() == object->map()->instance_size());
- ASSERT(map->instance_type() == object->map()->instance_type());
-
- // Allocate the backing storage for the properties.
- int prop_size = map->unused_property_fields() - map->inobject_properties();
- Object* properties;
- { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, TENURED);
- if (!maybe_properties->ToObject(&properties)) return maybe_properties;
- }
-
- // Reset the map for the object.
- object->set_map(constructor->initial_map());
-
- // Reinitialize the object from the constructor map.
- InitializeJSObjectFromMap(object, FixedArray::cast(properties), map);
- return object;
-}
-
-
-MaybeObject* Heap::AllocateStringFromOneByte(Vector<const uint8_t> string,
- PretenureFlag pretenure) {
- int length = string.length();
- if (length == 1) {
- return Heap::LookupSingleCharacterStringFromCode(string[0]);
- }
- Object* result;
- { MaybeObject* maybe_result =
- AllocateRawOneByteString(string.length(), pretenure);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
-
- // Copy the characters into the new object.
- CopyChars(SeqOneByteString::cast(result)->GetChars(),
- string.start(),
- length);
- return result;
-}
-
-
MaybeObject* Heap::AllocateStringFromUtf8Slow(Vector<const char> string,
int non_ascii_start,
PretenureFlag pretenure) {
@@ -4526,7 +3979,9 @@
{
int chars = non_ascii_start + utf16_length;
MaybeObject* maybe_result = AllocateRawTwoByteString(chars, pretenure);
- if (!maybe_result->ToObject(&result)) return maybe_result;
+ if (!maybe_result->ToObject(&result) || result->IsException()) {
+ return maybe_result;
+ }
}
// Convert and copy the characters into the new object.
SeqTwoByteString* twobyte = SeqTwoByteString::cast(result);
@@ -4553,11 +4008,15 @@
if (String::IsOneByte(start, length)) {
MaybeObject* maybe_result = AllocateRawOneByteString(length, pretenure);
- if (!maybe_result->ToObject(&result)) return maybe_result;
+ if (!maybe_result->ToObject(&result) || result->IsException()) {
+ return maybe_result;
+ }
CopyChars(SeqOneByteString::cast(result)->GetChars(), start, length);
} else { // It's not a one byte string.
MaybeObject* maybe_result = AllocateRawTwoByteString(length, pretenure);
- if (!maybe_result->ToObject(&result)) return maybe_result;
+ if (!maybe_result->ToObject(&result) || result->IsException()) {
+ return maybe_result;
+ }
CopyChars(SeqTwoByteString::cast(result)->GetChars(), start, length);
}
return result;
@@ -4908,21 +4367,6 @@
}
-MaybeObject* Heap::AllocateEmptyFixedDoubleArray() {
- int size = FixedDoubleArray::SizeFor(0);
- Object* result;
- { MaybeObject* maybe_result =
- AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- // Initialize the object.
- reinterpret_cast<FixedDoubleArray*>(result)->set_map_no_write_barrier(
- fixed_double_array_map());
- reinterpret_cast<FixedDoubleArray*>(result)->set_length(0);
- return result;
-}
-
-
MaybeObject* Heap::AllocateUninitializedFixedDoubleArray(
int length,
PretenureFlag pretenure) {
@@ -5405,6 +4849,7 @@
#ifdef VERIFY_HEAP
void Heap::Verify() {
CHECK(HasBeenSetUp());
+ HandleScope scope(isolate());
store_buffer()->Verify();
@@ -5881,6 +5326,12 @@
code_range_size_ = code_range_size;
+ // We set the old generation growing factor to 2 to grow the heap slower on
+ // memory-constrained devices.
+ if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) {
+ old_space_growing_factor_ = 2;
+ }
+
configured_ = true;
return true;
}
@@ -6104,16 +5555,12 @@
// Create initial objects
if (!CreateInitialObjects()) return false;
+ CHECK_EQ(0, gc_count_);
native_contexts_list_ = undefined_value();
array_buffers_list_ = undefined_value();
allocation_sites_list_ = undefined_value();
weak_object_to_code_table_ = undefined_value();
-
- HandleScope scope(isolate());
- Runtime::InitializeIntrinsicFunctionNames(
- isolate(), handle(intrinsic_function_names(), isolate()));
-
return true;
}
diff --git a/src/heap.h b/src/heap.h
index a732baa..c44d99e 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -60,6 +60,7 @@
V(Oddball, true_value, TrueValue) \
V(Oddball, false_value, FalseValue) \
V(Oddball, uninitialized_value, UninitializedValue) \
+ V(Oddball, exception, Exception) \
V(Map, cell_map, CellMap) \
V(Map, global_property_cell_map, GlobalPropertyCellMap) \
V(Map, shared_function_info_map, SharedFunctionInfoMap) \
@@ -187,6 +188,7 @@
V(Map, uninitialized_map, UninitializedMap) \
V(Map, arguments_marker_map, ArgumentsMarkerMap) \
V(Map, no_interceptor_result_sentinel_map, NoInterceptorResultSentinelMap) \
+ V(Map, exception_map, ExceptionMap) \
V(Map, termination_exception_map, TerminationExceptionMap) \
V(Map, message_object_map, JSMessageObjectMap) \
V(Map, foreign_map, ForeignMap) \
@@ -348,7 +350,6 @@
"KeyedStoreElementMonomorphic") \
V(stack_overflow_string, "kStackOverflowBoilerplate") \
V(illegal_access_string, "illegal access") \
- V(illegal_execution_state_string, "illegal execution state") \
V(get_string, "get") \
V(set_string, "set") \
V(map_field_string, "%map") \
@@ -723,34 +724,6 @@
MUST_USE_RESULT MaybeObject* CopyJSObject(JSObject* source,
AllocationSite* site = NULL);
- // Allocates a Harmony proxy or function proxy.
- // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
- // failed.
- // Please note this does not perform a garbage collection.
- MUST_USE_RESULT MaybeObject* AllocateJSProxy(Object* handler,
- Object* prototype);
-
- MUST_USE_RESULT MaybeObject* AllocateJSFunctionProxy(Object* handler,
- Object* call_trap,
- Object* construct_trap,
- Object* prototype);
-
- // Reinitialize a JSReceiver into an (empty) JS object of respective type and
- // size, but keeping the original prototype. The receiver must have at least
- // the size of the new object. The object is reinitialized and behaves as an
- // object that has been freshly allocated.
- // Returns failure if an error occured, otherwise object.
- MUST_USE_RESULT MaybeObject* ReinitializeJSReceiver(JSReceiver* object,
- InstanceType type,
- int size);
-
- // Reinitialize an JSGlobalProxy based on a constructor. The object
- // must have the same size as objects allocated using the
- // constructor. The object is reinitialized and behaves as an
- // object that has been freshly allocated using the constructor.
- MUST_USE_RESULT MaybeObject* ReinitializeJSGlobalProxy(
- JSFunction* constructor, JSGlobalProxy* global);
-
// Allocates and initializes a new JavaScript object based on a map.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
@@ -783,15 +756,15 @@
MUST_USE_RESULT MaybeObject* AllocatePartialMap(InstanceType instance_type,
int instance_size);
- // Allocates an empty code cache.
- MUST_USE_RESULT MaybeObject* AllocateCodeCache();
+ // Allocate a block of memory in the given space (filled with a filler).
+ // Used as a fall-back for generated code when the space is full.
+ MUST_USE_RESULT MaybeObject* AllocateFillerObject(int size,
+ bool double_align,
+ AllocationSpace space);
// Allocates an empty PolymorphicCodeCache.
MUST_USE_RESULT MaybeObject* AllocatePolymorphicCodeCache();
- // Allocates an AliasedArgumentsEntry.
- MUST_USE_RESULT MaybeObject* AllocateAliasedArgumentsEntry(int slot);
-
// Clear the Instanceof cache (used when a prototype changes).
inline void ClearInstanceofCache();
@@ -819,19 +792,6 @@
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
// Please note this does not perform a garbage collection.
- MUST_USE_RESULT MaybeObject* AllocateStringFromOneByte(
- Vector<const uint8_t> str,
- PretenureFlag pretenure = NOT_TENURED);
- // TODO(dcarney): remove this function.
- MUST_USE_RESULT inline MaybeObject* AllocateStringFromOneByte(
- Vector<const char> str,
- PretenureFlag pretenure = NOT_TENURED) {
- return AllocateStringFromOneByte(Vector<const uint8_t>::cast(str),
- pretenure);
- }
- MUST_USE_RESULT inline MaybeObject* AllocateStringFromUtf8(
- Vector<const char> str,
- PretenureFlag pretenure = NOT_TENURED);
MUST_USE_RESULT MaybeObject* AllocateStringFromUtf8Slow(
Vector<const char> str,
int non_ascii_start,
@@ -868,20 +828,6 @@
MUST_USE_RESULT MaybeObject* AllocateInternalizedStringImpl(
T t, int chars, uint32_t hash_field);
- // Allocates and partially initializes a String. There are two String
- // encodings: ASCII and two byte. These functions allocate a string of the
- // given length and set its map and length fields. The characters of the
- // string are uninitialized.
- // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
- // failed.
- // Please note this does not perform a garbage collection.
- MUST_USE_RESULT MaybeObject* AllocateRawOneByteString(
- int length,
- PretenureFlag pretenure = NOT_TENURED);
- MUST_USE_RESULT MaybeObject* AllocateRawTwoByteString(
- int length,
- PretenureFlag pretenure = NOT_TENURED);
-
// Computes a single character string where the character has code.
// A cache is used for ASCII codes.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
@@ -923,9 +869,6 @@
MUST_USE_RESULT MaybeObject* AllocateSymbol();
MUST_USE_RESULT MaybeObject* AllocatePrivateSymbol();
- // Allocate a tenured AllocationSite. It's payload is null
- MUST_USE_RESULT MaybeObject* AllocateAllocationSite();
-
// Allocates a fixed array initialized with undefined values
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
@@ -998,16 +941,6 @@
// Allocates a new utility object in the old generation.
MUST_USE_RESULT MaybeObject* AllocateStruct(InstanceType type);
- // Allocates a function initialized with a shared part.
- // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
- // failed.
- // Please note this does not perform a garbage collection.
- MUST_USE_RESULT MaybeObject* AllocateFunction(
- Map* function_map,
- SharedFunctionInfo* shared,
- Object* prototype,
- PretenureFlag pretenure = TENURED);
-
// Sloppy mode arguments object size.
static const int kSloppyArgumentsObjectSize =
JSObject::kHeaderSize + 2 * kPointerSize;
@@ -1026,11 +959,6 @@
MUST_USE_RESULT MaybeObject* AllocateArgumentsObject(
Object* callee, int length);
- // Same as NewNumberFromDouble, but may return a preallocated/immutable
- // number object (e.g., minus_zero_value_, nan_value_)
- MUST_USE_RESULT MaybeObject* NumberFromDouble(
- double value, PretenureFlag pretenure = NOT_TENURED);
-
// Allocated a HeapNumber from value.
MUST_USE_RESULT MaybeObject* AllocateHeapNumber(
double value, PretenureFlag pretenure = NOT_TENURED);
@@ -1039,13 +967,6 @@
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
// Please note this does not perform a garbage collection.
- MUST_USE_RESULT inline MaybeObject* NumberFromInt32(
- int32_t value, PretenureFlag pretenure = NOT_TENURED);
-
- // Converts an int into either a Smi or a HeapNumber object.
- // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
- // failed.
- // Please note this does not perform a garbage collection.
MUST_USE_RESULT inline MaybeObject* NumberFromUint32(
uint32_t value, PretenureFlag pretenure = NOT_TENURED);
@@ -1056,47 +977,10 @@
MUST_USE_RESULT MaybeObject* AllocateForeign(
Address address, PretenureFlag pretenure = NOT_TENURED);
- // Allocates a new SharedFunctionInfo object.
- // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
- // failed.
- // Please note this does not perform a garbage collection.
- MUST_USE_RESULT MaybeObject* AllocateSharedFunctionInfo(Object* name);
-
- // Allocates a new JSMessageObject object.
- // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
- // failed.
- // Please note that this does not perform a garbage collection.
- MUST_USE_RESULT MaybeObject* AllocateJSMessageObject(
- String* type,
- JSArray* arguments,
- int start_position,
- int end_position,
- Object* script,
- Object* stack_frames);
-
- // Allocate a new external string object, which is backed by a string
- // resource that resides outside the V8 heap.
- // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
- // failed.
- // Please note this does not perform a garbage collection.
- MUST_USE_RESULT MaybeObject* AllocateExternalStringFromAscii(
- const ExternalAsciiString::Resource* resource);
- MUST_USE_RESULT MaybeObject* AllocateExternalStringFromTwoByte(
- const ExternalTwoByteString::Resource* resource);
-
// Finalizes an external string by deleting the associated external
// data and clearing the resource pointer.
inline void FinalizeExternalString(String* string);
- // Allocates an uninitialized object. The memory is non-executable if the
- // hardware and OS allow.
- // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
- // failed.
- // Please note this function does not perform a garbage collection.
- MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes,
- AllocationSpace space,
- AllocationSpace retry_space);
-
// Initialize a filler object to keep the ability to iterate over the heap
// when shortening objects.
void CreateFillerObjectAt(Address addr, int size);
@@ -1108,19 +992,7 @@
// Maintain marking consistency for IncrementalMarking.
void AdjustLiveBytes(Address address, int by, InvocationMode mode);
- // Makes a new native code object
- // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
- // failed. On success, the pointer to the Code object is stored in the
- // self_reference. This allows generated code to reference its own Code
- // object by containing this pointer.
- // Please note this function does not perform a garbage collection.
- MUST_USE_RESULT MaybeObject* CreateCode(
- const CodeDesc& desc,
- Code::Flags flags,
- Handle<Object> self_reference,
- bool immovable = false,
- bool crankshafted = false,
- int prologue_offset = Code::kPrologueOffsetNotSet);
+ MUST_USE_RESULT MaybeObject* AllocateCode(int object_size, bool immovable);
MUST_USE_RESULT MaybeObject* CopyCode(Code* code);
@@ -1451,13 +1323,6 @@
bool CreateApiObjects();
- // Attempt to find the number in a small cache. If we finds it, return
- // the string representation of the number. Otherwise return undefined.
- Object* GetNumberStringCache(Object* number);
-
- // Update the cache with a new number-string pair.
- void SetNumberStringCache(Object* number, String* str);
-
// Adjusts the amount of registered external memory.
// Returns the adjusted value.
inline int64_t AdjustAmountOfExternalAllocatedMemory(
@@ -1497,9 +1362,30 @@
static const intptr_t kMinimumOldGenerationAllocationLimit =
8 * (Page::kPageSize > MB ? Page::kPageSize : MB);
+ static const int kLumpOfMemory = (i::kPointerSize / 4) * i::MB;
+
+ // The new space size has to be a power of 2.
+ static const int kMaxNewSpaceSizeLowMemoryDevice = 2 * kLumpOfMemory;
+ static const int kMaxNewSpaceSizeMediumMemoryDevice = 8 * kLumpOfMemory;
+ static const int kMaxNewSpaceSizeHighMemoryDevice = 16 * kLumpOfMemory;
+ static const int kMaxNewSpaceSizeHugeMemoryDevice = 16 * kLumpOfMemory;
+
+ // The old space size has to be a multiple of Page::kPageSize.
+ static const int kMaxOldSpaceSizeLowMemoryDevice = 128 * kLumpOfMemory;
+ static const int kMaxOldSpaceSizeMediumMemoryDevice = 256 * kLumpOfMemory;
+ static const int kMaxOldSpaceSizeHighMemoryDevice = 512 * kLumpOfMemory;
+ static const int kMaxOldSpaceSizeHugeMemoryDevice = 700 * kLumpOfMemory;
+
+ // The executable size has to be a multiple of Page::kPageSize.
+ static const int kMaxExecutableSizeLowMemoryDevice = 128 * kLumpOfMemory;
+ static const int kMaxExecutableSizeMediumMemoryDevice = 256 * kLumpOfMemory;
+ static const int kMaxExecutableSizeHighMemoryDevice = 512 * kLumpOfMemory;
+ static const int kMaxExecutableSizeHugeMemoryDevice = 700 * kLumpOfMemory;
+
intptr_t OldGenerationAllocationLimit(intptr_t old_gen_size) {
- intptr_t limit = FLAG_stress_compaction ?
- old_gen_size + old_gen_size / 10 : old_gen_size * 4;
+ intptr_t limit = FLAG_stress_compaction
+ ? old_gen_size + old_gen_size / 10
+ : old_gen_size * old_space_growing_factor_;
limit = Max(limit, kMinimumOldGenerationAllocationLimit);
limit += new_space_.Capacity();
intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2;
@@ -1554,11 +1440,6 @@
// Generated code can treat direct references to this root as constant.
bool RootCanBeTreatedAsConstant(RootListIndex root_index);
- MUST_USE_RESULT MaybeObject* NumberToString(
- Object* number, bool check_number_string_cache = true);
- MUST_USE_RESULT MaybeObject* Uint32ToString(
- uint32_t value, bool check_number_string_cache = true);
-
Map* MapForFixedTypedArray(ExternalArrayType array_type);
RootListIndex RootIndexForFixedTypedArray(
ExternalArrayType array_type);
@@ -1865,6 +1746,11 @@
intptr_t max_executable_size_;
intptr_t maximum_committed_;
+ // The old space growing factor is used in the old space heap growing
+ // strategy. The new old space size is the current old space size times
+ // old_space_growing_factor_.
+ int old_space_growing_factor_;
+
// For keeping track of how much data has survived
// scavenge since last new space expansion.
int survived_since_last_expansion_;
@@ -2091,6 +1977,14 @@
return (pretenure == TENURED) ? preferred_old_space : NEW_SPACE;
}
+ // Allocate an uninitialized object. The memory is non-executable if the
+ // hardware and OS allow. This is the single choke-point for allocations
+ // performed by the runtime and should not be bypassed (to extend this to
+ // inlined allocations, use the Heap::DisableInlineAllocation() support).
+ MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes,
+ AllocationSpace space,
+ AllocationSpace retry_space);
+
// Allocate an uninitialized fixed array.
MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(
int length, PretenureFlag pretenure);
@@ -2103,6 +1997,15 @@
MUST_USE_RESULT MaybeObject* AllocateFixedArrayWithFiller(
int length, PretenureFlag pretenure, Object* filler);
+ // Allocate and partially initializes a String. There are two String
+ // encodings: ASCII and two byte. These functions allocate a string of the
+ // given length and set its map and length fields. The characters of the
+ // string are uninitialized.
+ MUST_USE_RESULT MaybeObject* AllocateRawOneByteString(
+ int length, PretenureFlag pretenure);
+ MUST_USE_RESULT MaybeObject* AllocateRawTwoByteString(
+ int length, PretenureFlag pretenure);
+
// Initializes a JSObject based on its map.
void InitializeJSObjectFromMap(JSObject* obj,
FixedArray* properties,
@@ -2120,11 +2023,6 @@
void CreateFixedStubs();
- MUST_USE_RESULT MaybeObject* CreateOddball(Map* map,
- const char* to_string,
- Object* to_number,
- byte kind);
-
// Allocate empty fixed array.
MUST_USE_RESULT MaybeObject* AllocateEmptyFixedArray();
@@ -2136,9 +2034,6 @@
MUST_USE_RESULT MaybeObject* AllocateEmptyFixedTypedArray(
ExternalArrayType array_type);
- // Allocate empty fixed double array.
- MUST_USE_RESULT MaybeObject* AllocateEmptyFixedDoubleArray();
-
// Allocate empty constant pool array.
MUST_USE_RESULT MaybeObject* AllocateEmptyConstantPoolArray();
@@ -2198,16 +2093,6 @@
// Slow part of scavenge object.
static void ScavengeObjectSlow(HeapObject** p, HeapObject* object);
- // Initializes a function with a shared part and prototype.
- // Note: this code was factored out of AllocateFunction such that
- // other parts of the VM could use it. Specifically, a function that creates
- // instances of type JS_FUNCTION_TYPE benefit from the use of this function.
- // Please note this does not perform a garbage collection.
- inline void InitializeFunction(
- JSFunction* function,
- SharedFunctionInfo* shared,
- Object* prototype);
-
// Total RegExp code ever generated
double total_regexp_code_generated_;
@@ -2216,9 +2101,6 @@
// Allocates a small number to string cache.
MUST_USE_RESULT MaybeObject* AllocateInitialNumberStringCache();
// Creates and installs the full-sized number string cache.
- void AllocateFullSizeNumberStringCache();
- // Get the length of the number to string cache based on the max semispace
- // size.
int FullSizeNumberStringCacheLength();
// Flush the number to string cache.
void FlushNumberStringCache();
@@ -2914,10 +2796,10 @@
ResultsCacheType type);
// Attempt to add value_array to the cache specified by type. On success,
// value_array is turned into a COW-array.
- static void Enter(Heap* heap,
- String* key_string,
- Object* key_pattern,
- FixedArray* value_array,
+ static void Enter(Isolate* isolate,
+ Handle<String> key_string,
+ Handle<Object> key_pattern,
+ Handle<FixedArray> value_array,
ResultsCacheType type);
static void Clear(FixedArray* cache);
static const int kRegExpResultsCacheSize = 0x100;
diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc
index 52a5492..66851b0 100644
--- a/src/hydrogen-check-elimination.cc
+++ b/src/hydrogen-check-elimination.cc
@@ -305,7 +305,7 @@
if (entry != NULL) {
// entry found;
MapSet a = entry->maps_;
- MapSet i = instr->map_set().Copy(phase_->zone());
+ MapSet i = instr->map_set()->Copy(phase_->zone());
if (a->IsSubset(i)) {
// The first check is more strict; the second is redundant.
if (entry->check_ != NULL) {
@@ -364,7 +364,7 @@
}
} else {
// No entry; insert a new one.
- Insert(object, instr, instr->map_set().Copy(phase_->zone()));
+ Insert(object, instr, instr->map_set()->Copy(phase_->zone()));
}
}
@@ -382,7 +382,13 @@
void ReduceLoadNamedField(HLoadNamedField* instr) {
// Reduce a load of the map field when it is known to be a constant.
- if (!IsMapAccess(instr->access())) return;
+ if (!IsMapAccess(instr->access())) {
+ // Check if we introduce field maps here.
+ if (instr->map_set()->size() != 0) {
+ Insert(instr, instr, instr->map_set()->Copy(phase_->zone()));
+ }
+ return;
+ }
HValue* object = instr->object()->ActualValue();
MapSet maps = FindMaps(object);
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 336c9f7..c56f5dc 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1247,6 +1247,13 @@
}
+void HBranch::PrintDataTo(StringStream* stream) {
+ HUnaryControlInstruction::PrintDataTo(stream);
+ stream->Add(" ");
+ expected_input_types().Print(stream);
+}
+
+
void HCompareMap::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
stream->Add(" (%p)", *map().handle());
@@ -3303,6 +3310,21 @@
}
+bool HCompareNumericAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
+ if (left() == right() &&
+ left()->representation().IsSmiOrInteger32()) {
+ *block = (token() == Token::EQ ||
+ token() == Token::EQ_STRICT ||
+ token() == Token::LTE ||
+ token() == Token::GTE)
+ ? FirstSuccessor() : SecondSuccessor();
+ return true;
+ }
+ *block = NULL;
+ return false;
+}
+
+
bool HCompareMinusZeroAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (FLAG_fold_constants && value()->IsConstant()) {
HConstant* constant = HConstant::cast(value());
@@ -3382,6 +3404,14 @@
object()->PrintNameTo(stream);
access_.PrintTo(stream);
+ if (map_set_.size() != 0) {
+ stream->Add(" [%p", *map_set_.at(0).handle());
+ for (int i = 1; i < map_set_.size(); ++i) {
+ stream->Add(",%p", *map_set_.at(i).handle());
+ }
+ stream->Add("]");
+ }
+
if (HasDependency()) {
stream->Add(" ");
dependency()->PrintNameTo(stream);
@@ -3403,8 +3433,8 @@
// TODO(titzer): collect dependent map checks into a list.
check_map->omit_ = true;
if (map->CanTransition()) {
- map->AddDependentCompilationInfo(
- DependentCode::kPrototypeCheckGroup, info);
+ Map::AddDependentCompilationInfo(
+ map, DependentCode::kPrototypeCheckGroup, info);
}
}
return check_map;
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 26501d0..3b486e7 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -1543,6 +1543,8 @@
virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
+ virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+
ToBooleanStub::Types expected_input_types() const {
return expected_input_types_;
}
@@ -2770,7 +2772,7 @@
HValue* typecheck() { return OperandAt(1); }
Unique<Map> first_map() const { return map_set_.at(0); }
- UniqueSet<Map> map_set() const { return map_set_; }
+ const UniqueSet<Map>* map_set() const { return &map_set_; }
void set_map_set(UniqueSet<Map>* maps, Zone *zone) {
map_set_.Clear();
@@ -4218,6 +4220,9 @@
virtual Representation observed_input_representation(int index) V8_OVERRIDE {
return observed_input_representation_[index];
}
+
+ virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
+
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
void SetOperandPositions(Zone* zone,
@@ -6144,6 +6149,22 @@
public:
DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*, HValue*,
HObjectAccess);
+ static HLoadNamedField* New(Zone* zone, HValue* context,
+ HValue* object, HValue* dependency,
+ HObjectAccess access, SmallMapList* maps,
+ CompilationInfo* info) {
+ HLoadNamedField* load_named_field = HLoadNamedField::New(
+ zone, context, object, dependency, access);
+ for (int i = 0; i < maps->length(); ++i) {
+ Handle<Map> map(maps->at(i));
+ load_named_field->map_set_.Add(Unique<Map>(map), zone);
+ if (map->CanTransition()) {
+ Map::AddDependentCompilationInfo(
+ map, DependentCode::kPrototypeCheckGroup, info);
+ }
+ }
+ return load_named_field;
+ }
HValue* object() { return OperandAt(0); }
HValue* dependency() {
@@ -6156,6 +6177,8 @@
return access_.representation();
}
+ const UniqueSet<Map>* map_set() const { return &map_set_; }
+
virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
return !access().IsInobject() || access().offset() >= size;
@@ -6175,13 +6198,15 @@
protected:
virtual bool DataEquals(HValue* other) V8_OVERRIDE {
HLoadNamedField* b = HLoadNamedField::cast(other);
- return access_.Equals(b->access_);
+ return access_.Equals(b->access_) && this->map_set_.Equals(&b->map_set_);
}
private:
HLoadNamedField(HValue* object,
HValue* dependency,
- HObjectAccess access) : access_(access) {
+ HObjectAccess access,
+ Handle<Map> map = Handle<Map>::null())
+ : access_(access) {
ASSERT(object != NULL);
SetOperandAt(0, object);
SetOperandAt(1, dependency != NULL ? dependency : object);
@@ -6215,6 +6240,7 @@
virtual bool IsDeletable() const V8_OVERRIDE { return true; }
HObjectAccess access_;
+ UniqueSet<Map> map_set_;
};
@@ -6594,7 +6620,8 @@
ASSERT(!has_transition()); // Only set once.
Handle<Map> map = Handle<Map>::cast(map_constant->handle(info->isolate()));
if (map->CanBeDeprecated()) {
- map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info);
+ Map::AddDependentCompilationInfo(
+ map, DependentCode::kTransitionGroup, info);
}
SetOperandAt(2, map_constant);
has_transition_ = true;
diff --git a/src/hydrogen-load-elimination.cc b/src/hydrogen-load-elimination.cc
index f84eac0..0947934 100644
--- a/src/hydrogen-load-elimination.cc
+++ b/src/hydrogen-load-elimination.cc
@@ -78,7 +78,10 @@
HValue* result = load(l);
if (result != instr &&
result->type().Equals(instr->type()) &&
- result->representation().Equals(instr->representation())) {
+ result->representation().Equals(instr->representation()) &&
+ (!result->IsLoadNamedField() ||
+ HLoadNamedField::cast(instr)->map_set()->IsSubset(
+ HLoadNamedField::cast(result)->map_set()))) {
// The load can be replaced with a previous load or a value.
TRACE((" replace L%d -> v%d\n", instr->id(), result->id()));
instr->DeleteAndReplaceWith(result);
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index cf34517..843be65 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1314,11 +1314,8 @@
HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
HValue* max_capacity = AddUncasted<HAdd>(current_capacity, max_gap);
- IfBuilder key_checker(this);
- key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT);
- key_checker.Then();
- key_checker.ElseDeopt("Key out of capacity range");
- key_checker.End();
+
+ Add<HBoundsCheck>(key, max_capacity);
HValue* new_capacity = BuildNewElementsCapacity(key);
HValue* new_elements = BuildGrowElementsCapacity(object, elements,
@@ -2621,6 +2618,15 @@
}
if (length > 0) {
+ // We have to initialize the elements pointer if allocation folding is
+ // turned off.
+ if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
+ HConstant* empty_fixed_array = Add<HConstant>(
+ isolate()->factory()->empty_fixed_array());
+ Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
+ empty_fixed_array, INITIALIZING_STORE);
+ }
+
HValue* boilerplate_elements = AddLoadElements(boilerplate);
HValue* object_elements;
if (IsFastDoubleElementsKind(kind)) {
@@ -4925,8 +4931,8 @@
Handle<GlobalObject> global(current_info()->global_object());
Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
if (cell->type()->IsConstant()) {
- cell->AddDependentCompilationInfo(top_info());
- Handle<Object> constant_object = cell->type()->AsConstant();
+ PropertyCell::AddDependentCompilationInfo(cell, top_info());
+ Handle<Object> constant_object = cell->type()->AsConstant()->Value();
if (constant_object->IsConsString()) {
constant_object =
String::Flatten(Handle<String>::cast(constant_object));
@@ -4999,7 +5005,7 @@
static bool CanInlinePropertyAccess(Type* type) {
if (type->Is(Type::NumberOrString())) return true;
if (!type->IsClass()) return false;
- Handle<Map> map = type->AsClass();
+ Handle<Map> map = type->AsClass()->Map();
return map->IsJSObjectMap() &&
!map->is_dictionary_map() &&
!map->has_named_interceptor();
@@ -5370,7 +5376,7 @@
access = HObjectAccess::ForHeapNumberValue();
}
return New<HLoadNamedField>(
- checked_object, static_cast<HValue*>(NULL), access);
+ checked_object, checked_object, access, info->field_maps(), top_info());
}
@@ -5380,8 +5386,7 @@
HValue* value) {
bool transition_to_field = info->lookup()->IsTransition();
// TODO(verwaest): Move this logic into PropertyAccessInfo.
- HObjectAccess field_access = HObjectAccess::ForField(
- info->map(), info->lookup(), info->name());
+ HObjectAccess field_access = info->access();
HStoreNamedField *instr;
if (field_access.representation().IsDouble()) {
@@ -5415,6 +5420,23 @@
value, STORE_TO_INITIALIZED_ENTRY);
}
} else {
+ if (!info->field_maps()->is_empty()) {
+ ASSERT(field_access.representation().IsHeapObject());
+ BuildCheckHeapObject(value);
+ if (info->field_maps()->length() == 1) {
+ // TODO(bmeurer): Also apply stable maps optimization to the else case!
+ value = BuildCheckMap(value, info->field_maps()->first());
+ } else {
+ value = Add<HCheckMaps>(value, info->field_maps());
+ }
+
+ // TODO(bmeurer): This is a dirty hack to avoid repeating the smi check
+ // that was already performed by the HCheckHeapObject above in the
+ // HStoreNamedField below. We should really do this right instead and
+ // make Crankshaft aware of Representation::HeapObject().
+ field_access = field_access.WithRepresentation(Representation::Tagged());
+ }
+
// This is a normal store.
instr = New<HStoreNamedField>(
checked_object->ActualValue(), field_access, value,
@@ -5478,6 +5500,25 @@
}
if (info->access_.offset() != access_.offset()) return false;
if (info->access_.IsInobject() != access_.IsInobject()) return false;
+ if (IsLoad()) {
+ if (field_maps_.is_empty()) {
+ info->field_maps_.Clear();
+ } else if (!info->field_maps_.is_empty()) {
+ for (int i = 0; i < field_maps_.length(); ++i) {
+ info->field_maps_.AddMapIfMissing(field_maps_.at(i), info->zone());
+ }
+ info->field_maps_.Sort();
+ }
+ } else {
+ // We can only merge stores that agree on their field maps. The comparison
+ // below is safe, since we keep the field maps sorted.
+ if (field_maps_.length() != info->field_maps_.length()) return false;
+ for (int i = 0; i < field_maps_.length(); ++i) {
+ if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) {
+ return false;
+ }
+ }
+ }
info->GeneralizeRepresentation(r);
return true;
}
@@ -5497,7 +5538,11 @@
}
if (lookup_.IsField()) {
+ // Construct the object field access.
access_ = HObjectAccess::ForField(map, &lookup_, name_);
+
+ // Load field map for heap objects.
+ LoadFieldMaps(map);
} else if (lookup_.IsPropertyCallbacks()) {
Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate());
if (!callback->IsAccessorPair()) return false;
@@ -5524,6 +5569,39 @@
}
+void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
+ Handle<Map> map) {
+ // Clear any previously collected field maps.
+ field_maps_.Clear();
+
+ // Figure out the field type from the accessor map.
+ Handle<HeapType> field_type(lookup_.GetFieldTypeFromMap(*map), isolate());
+
+ // Collect the (stable) maps from the field type.
+ int num_field_maps = field_type->NumClasses();
+ if (num_field_maps == 0) return;
+ ASSERT(access_.representation().IsHeapObject());
+ field_maps_.Reserve(num_field_maps, zone());
+ HeapType::Iterator<Map> it = field_type->Classes();
+ while (!it.Done()) {
+ Handle<Map> field_map = it.Current();
+ if (!field_map->is_stable()) {
+ field_maps_.Clear();
+ return;
+ }
+ field_maps_.Add(field_map, zone());
+ it.Advance();
+ }
+ field_maps_.Sort();
+ ASSERT_EQ(num_field_maps, field_maps_.length());
+
+ // Add dependency on the map that introduced the field.
+ Map::AddDependentCompilationInfo(
+ handle(lookup_.GetFieldOwnerFromMap(*map), isolate()),
+ DependentCode::kFieldTypeGroup, top_info());
+}
+
+
bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
Handle<Map> map = this->map();
@@ -5560,6 +5638,11 @@
Handle<Map> map = this->map();
map->LookupTransition(NULL, *name_, &lookup_);
if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) {
+ // Construct the object field access.
+ access_ = HObjectAccess::ForField(map, &lookup_, name_);
+
+ // Load field map for heap objects.
+ LoadFieldMaps(transition());
return true;
}
return false;
@@ -5914,7 +5997,7 @@
Handle<GlobalObject> global(current_info()->global_object());
Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
if (cell->type()->IsConstant()) {
- Handle<Object> constant = cell->type()->AsConstant();
+ Handle<Object> constant = cell->type()->AsConstant()->Value();
if (value->IsConstant()) {
HConstant* c_value = HConstant::cast(value);
if (!constant.is_identical_to(c_value->handle(isolate()))) {
@@ -6782,16 +6865,16 @@
HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
CompilationInfo* info) {
HConstant* constant_value = New<HConstant>(constant);
+ Handle<Map> map(constant->map(), info->isolate());
if (constant->map()->CanOmitMapChecks()) {
- constant->map()->AddDependentCompilationInfo(
- DependentCode::kPrototypeCheckGroup, info);
+ Map::AddDependentCompilationInfo(
+ map, DependentCode::kPrototypeCheckGroup, info);
return constant_value;
}
AddInstruction(constant_value);
- HCheckMaps* check =
- Add<HCheckMaps>(constant_value, handle(constant->map()), info);
+ HCheckMaps* check = Add<HCheckMaps>(constant_value, map, info);
check->ClearDependsOnFlag(kElementsKind);
return check;
}
@@ -6879,13 +6962,36 @@
}
+class FunctionSorter {
+ public:
+ FunctionSorter(int index = 0, int ticks = 0, int size = 0)
+ : index_(index), ticks_(ticks), size_(size) { }
+
+ int index() const { return index_; }
+ int ticks() const { return ticks_; }
+ int size() const { return size_; }
+
+ private:
+ int index_;
+ int ticks_;
+ int size_;
+};
+
+
+inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
+ int diff = lhs.ticks() - rhs.ticks();
+ if (diff != 0) return diff > 0;
+ return lhs.size() < rhs.size();
+}
+
+
void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
Call* expr,
HValue* receiver,
SmallMapList* types,
Handle<String> name) {
int argument_count = expr->arguments()->length() + 1; // Includes receiver.
- int order[kMaxCallPolymorphism];
+ FunctionSorter order[kMaxCallPolymorphism];
bool handle_smi = false;
bool handled_string = false;
@@ -6907,17 +7013,20 @@
handle_smi = true;
}
expr->set_target(target);
- order[ordered_functions++] = i;
+ order[ordered_functions++] = FunctionSorter(
+ i, target->shared()->profiler_ticks(), InliningAstSize(target));
}
}
+ std::sort(order, order + ordered_functions);
+
HBasicBlock* number_block = NULL;
HBasicBlock* join = NULL;
handled_string = false;
int count = 0;
for (int fn = 0; fn < ordered_functions; ++fn) {
- int i = order[fn];
+ int i = order[fn].index();
PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
if (info.type()->Is(Type::String())) {
if (handled_string) continue;
@@ -7619,6 +7728,8 @@
if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
ElementsKind elements_kind = receiver_map->elements_kind();
if (!IsFastElementsKind(elements_kind)) return false;
+ if (receiver_map->is_observed()) return false;
+ ASSERT(receiver_map->is_extensible());
Drop(expr->arguments()->length());
HValue* result;
@@ -7681,6 +7792,8 @@
if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
ElementsKind elements_kind = receiver_map->elements_kind();
if (!IsFastElementsKind(elements_kind)) return false;
+ if (receiver_map->is_observed()) return false;
+ ASSERT(receiver_map->is_extensible());
// If there may be elements accessors in the prototype chain, the fast
// inlined version can't be used.
@@ -7693,31 +7806,34 @@
Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
- HValue* op_vals[] = {
- context(),
- // Receiver.
- environment()->ExpressionStackAt(expr->arguments()->length())
- };
-
const int argc = expr->arguments()->length();
- // Includes receiver.
- PushArgumentsFromEnvironment(argc + 1);
+ if (argc != 1) return false;
- CallInterfaceDescriptor* descriptor =
- isolate()->call_descriptor(Isolate::CallHandler);
+ HValue* value_to_push = Pop();
+ HValue* array = Pop();
- ArrayPushStub stub(receiver_map->elements_kind(), argc);
- Handle<Code> code = stub.GetCode(isolate());
- HConstant* code_value = Add<HConstant>(code);
+ HInstruction* new_size = NULL;
+ HValue* length = NULL;
- ASSERT((sizeof(op_vals) / kPointerSize) ==
- descriptor->environment_length());
+ {
+ NoObservableSideEffectsScope scope(this);
- HInstruction* call = New<HCallWithDescriptor>(
- code_value, argc + 1, descriptor,
- Vector<HValue*>(op_vals, descriptor->environment_length()));
+ length = Add<HLoadNamedField>(array, static_cast<HValue*>(NULL),
+ HObjectAccess::ForArrayLength(elements_kind));
+
+ new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
+
+ bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
+ BuildUncheckedMonomorphicElementAccess(array, length,
+ value_to_push, is_array,
+ elements_kind, STORE,
+ NEVER_RETURN_HOLE,
+ STORE_AND_GROW_NO_TRANSITION);
+ Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
+ }
+
Drop(1); // Drop function.
- ast_context()->ReturnInstruction(call, expr->id());
+ ast_context()->ReturnValue(new_size);
return true;
}
default:
@@ -9866,7 +9982,7 @@
HValue* operand_to_check =
left->block()->block_id() < right->block()->block_id() ? left : right;
if (combined_type->IsClass()) {
- Handle<Map> map = combined_type->AsClass();
+ Handle<Map> map = combined_type->AsClass()->Map();
AddCheckMap(operand_to_check, map);
HCompareObjectEqAndBranch* result =
New<HCompareObjectEqAndBranch>(left, right);
diff --git a/src/hydrogen.h b/src/hydrogen.h
index ac6b99d..c561ab1 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -438,9 +438,11 @@
void MarkDependsOnEmptyArrayProtoElements() {
// Add map dependency if not already added.
if (depends_on_empty_array_proto_elements_) return;
- isolate()->initial_object_prototype()->map()->AddDependentCompilationInfo(
+ Map::AddDependentCompilationInfo(
+ handle(isolate()->initial_object_prototype()->map()),
DependentCode::kElementsCantBeAddedGroup, info());
- isolate()->initial_array_prototype()->map()->AddDependentCompilationInfo(
+ Map::AddDependentCompilationInfo(
+ handle(isolate()->initial_array_prototype()->map()),
DependentCode::kElementsCantBeAddedGroup, info());
depends_on_empty_array_proto_elements_ = true;
}
@@ -2378,7 +2380,7 @@
context = context->native_context();
return handle(context->string_function()->initial_map());
} else {
- return type_->AsClass();
+ return type_->AsClass()->Map();
}
}
Type* type() const { return type_; }
@@ -2414,14 +2416,18 @@
Handle<JSFunction> accessor() { return accessor_; }
Handle<Object> constant() { return constant_; }
Handle<Map> transition() { return handle(lookup_.GetTransitionTarget()); }
+ SmallMapList* field_maps() { return &field_maps_; }
HObjectAccess access() { return access_; }
private:
Type* ToType(Handle<Map> map) { return builder_->ToType(map); }
+ Zone* zone() { return builder_->zone(); }
Isolate* isolate() { return lookup_.isolate(); }
+ CompilationInfo* top_info() { return builder_->top_info(); }
CompilationInfo* current_info() { return builder_->current_info(); }
bool LoadResult(Handle<Map> map);
+ void LoadFieldMaps(Handle<Map> map);
bool LookupDescriptor();
bool LookupInPrototypes();
bool IsCompatible(PropertyAccessInfo* other);
@@ -2440,6 +2446,7 @@
Handle<JSFunction> accessor_;
Handle<JSObject> api_holder_;
Handle<Object> constant_;
+ SmallMapList field_maps_;
HObjectAccess access_;
};
diff --git a/src/i18n.cc b/src/i18n.cc
index bfe4200..c3f9541 100644
--- a/src/i18n.cc
+++ b/src/i18n.cc
@@ -57,7 +57,7 @@
Handle<JSObject> options,
const char* key,
icu::UnicodeString* setting) {
- Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
+ Handle<String> str = isolate->factory()->NewStringFromAsciiChecked(key);
Handle<Object> object = Object::GetProperty(options, str).ToHandleChecked();
if (object->IsString()) {
v8::String::Utf8Value utf8_string(
@@ -73,7 +73,7 @@
Handle<JSObject> options,
const char* key,
int32_t* value) {
- Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
+ Handle<String> str = isolate->factory()->NewStringFromAsciiChecked(key);
Handle<Object> object = Object::GetProperty(options, str).ToHandleChecked();
if (object->IsNumber()) {
object->ToInt32(value);
@@ -87,7 +87,7 @@
Handle<JSObject> options,
const char* key,
bool* value) {
- Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
+ Handle<String> str = isolate->factory()->NewStringFromAsciiChecked(key);
Handle<Object> object = Object::GetProperty(options, str).ToHandleChecked();
if (object->IsBoolean()) {
*value = object->BooleanValue();
@@ -149,16 +149,17 @@
const icu::Locale& icu_locale,
icu::SimpleDateFormat* date_format,
Handle<JSObject> resolved) {
+ Factory* factory = isolate->factory();
UErrorCode status = U_ZERO_ERROR;
icu::UnicodeString pattern;
date_format->toPattern(pattern);
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("pattern")),
- isolate->factory()->NewStringFromTwoByte(
+ factory->NewStringFromStaticAscii("pattern"),
+ factory->NewStringFromTwoByte(
Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
- pattern.length())),
+ pattern.length())).ToHandleChecked(),
NONE,
SLOPPY).Assert();
@@ -167,8 +168,8 @@
const char* calendar_name = calendar->getType();
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("calendar")),
- isolate->factory()->NewStringFromAscii(CStrVector(calendar_name)),
+ factory->NewStringFromStaticAscii("calendar"),
+ factory->NewStringFromAsciiChecked(calendar_name),
NONE,
SLOPPY).Assert();
@@ -182,19 +183,19 @@
if (canonical_time_zone == UNICODE_STRING_SIMPLE("Etc/GMT")) {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("timeZone")),
- isolate->factory()->NewStringFromAscii(CStrVector("UTC")),
+ factory->NewStringFromStaticAscii("timeZone"),
+ factory->NewStringFromStaticAscii("UTC"),
NONE,
SLOPPY).Assert();
} else {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("timeZone")),
- isolate->factory()->NewStringFromTwoByte(
+ factory->NewStringFromStaticAscii("timeZone"),
+ factory->NewStringFromTwoByte(
Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(
canonical_time_zone.getBuffer()),
- canonical_time_zone.length())),
+ canonical_time_zone.length())).ToHandleChecked(),
NONE,
SLOPPY).Assert();
}
@@ -210,15 +211,15 @@
const char* ns = numbering_system->getName();
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
- isolate->factory()->NewStringFromAscii(CStrVector(ns)),
+ factory->NewStringFromStaticAscii("numberingSystem"),
+ factory->NewStringFromAsciiChecked(ns),
NONE,
SLOPPY).Assert();
} else {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
- isolate->factory()->undefined_value(),
+ factory->NewStringFromStaticAscii("numberingSystem"),
+ factory->undefined_value(),
NONE,
SLOPPY).Assert();
}
@@ -232,16 +233,16 @@
if (U_SUCCESS(status)) {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector(result)),
+ factory->NewStringFromStaticAscii("locale"),
+ factory->NewStringFromAsciiChecked(result),
NONE,
SLOPPY).Assert();
} else {
// This would never happen, since we got the locale from ICU.
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector("und")),
+ factory->NewStringFromStaticAscii("locale"),
+ factory->NewStringFromStaticAscii("und"),
NONE,
SLOPPY).Assert();
}
@@ -376,15 +377,16 @@
const icu::Locale& icu_locale,
icu::DecimalFormat* number_format,
Handle<JSObject> resolved) {
+ Factory* factory = isolate->factory();
icu::UnicodeString pattern;
number_format->toPattern(pattern);
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("pattern")),
- isolate->factory()->NewStringFromTwoByte(
+ factory->NewStringFromStaticAscii("pattern"),
+ factory->NewStringFromTwoByte(
Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
- pattern.length())),
+ pattern.length())).ToHandleChecked(),
NONE,
SLOPPY).Assert();
@@ -393,11 +395,11 @@
if (!currency.isEmpty()) {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("currency")),
- isolate->factory()->NewStringFromTwoByte(
+ factory->NewStringFromStaticAscii("currency"),
+ factory->NewStringFromTwoByte(
Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(currency.getBuffer()),
- currency.length())),
+ currency.length())).ToHandleChecked(),
NONE,
SLOPPY).Assert();
}
@@ -412,15 +414,15 @@
const char* ns = numbering_system->getName();
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
- isolate->factory()->NewStringFromAscii(CStrVector(ns)),
+ factory->NewStringFromStaticAscii("numberingSystem"),
+ factory->NewStringFromAsciiChecked(ns),
NONE,
SLOPPY).Assert();
} else {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
- isolate->factory()->undefined_value(),
+ factory->NewStringFromStaticAscii("numberingSystem"),
+ factory->undefined_value(),
NONE,
SLOPPY).Assert();
}
@@ -428,60 +430,49 @@
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("useGrouping")),
- isolate->factory()->ToBoolean(number_format->isGroupingUsed()),
+ factory->NewStringFromStaticAscii("useGrouping"),
+ factory->ToBoolean(number_format->isGroupingUsed()),
NONE,
SLOPPY).Assert();
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(
- CStrVector("minimumIntegerDigits")),
- isolate->factory()->NewNumberFromInt(
- number_format->getMinimumIntegerDigits()),
+ factory->NewStringFromStaticAscii("minimumIntegerDigits"),
+ factory->NewNumberFromInt(number_format->getMinimumIntegerDigits()),
NONE,
SLOPPY).Assert();
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(
- CStrVector("minimumFractionDigits")),
- isolate->factory()->NewNumberFromInt(
- number_format->getMinimumFractionDigits()),
+ factory->NewStringFromStaticAscii("minimumFractionDigits"),
+ factory->NewNumberFromInt(number_format->getMinimumFractionDigits()),
NONE,
SLOPPY).Assert();
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(
- CStrVector("maximumFractionDigits")),
- isolate->factory()->NewNumberFromInt(
- number_format->getMaximumFractionDigits()),
+ factory->NewStringFromStaticAscii("maximumFractionDigits"),
+ factory->NewNumberFromInt(number_format->getMaximumFractionDigits()),
NONE,
SLOPPY).Assert();
- Handle<String> key = isolate->factory()->NewStringFromAscii(
- CStrVector("minimumSignificantDigits"));
+ Handle<String> key =
+ factory->NewStringFromStaticAscii("minimumSignificantDigits");
if (JSReceiver::HasLocalProperty(resolved, key)) {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(
- CStrVector("minimumSignificantDigits")),
- isolate->factory()->NewNumberFromInt(
- number_format->getMinimumSignificantDigits()),
+ factory->NewStringFromStaticAscii("minimumSignificantDigits"),
+ factory->NewNumberFromInt(number_format->getMinimumSignificantDigits()),
NONE,
SLOPPY).Assert();
}
- key = isolate->factory()->NewStringFromAscii(
- CStrVector("maximumSignificantDigits"));
+ key = factory->NewStringFromStaticAscii("maximumSignificantDigits");
if (JSReceiver::HasLocalProperty(resolved, key)) {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(
- CStrVector("maximumSignificantDigits")),
- isolate->factory()->NewNumberFromInt(
- number_format->getMaximumSignificantDigits()),
+ factory->NewStringFromStaticAscii("maximumSignificantDigits"),
+ factory->NewNumberFromInt(number_format->getMaximumSignificantDigits()),
NONE,
SLOPPY).Assert();
}
@@ -494,16 +485,16 @@
if (U_SUCCESS(status)) {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector(result)),
+ factory->NewStringFromStaticAscii("locale"),
+ factory->NewStringFromAsciiChecked(result),
NONE,
SLOPPY).Assert();
} else {
// This would never happen, since we got the locale from ICU.
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector("und")),
+ factory->NewStringFromStaticAscii("locale"),
+ factory->NewStringFromStaticAscii("und"),
NONE,
SLOPPY).Assert();
}
@@ -578,12 +569,13 @@
const icu::Locale& icu_locale,
icu::Collator* collator,
Handle<JSObject> resolved) {
+ Factory* factory = isolate->factory();
UErrorCode status = U_ZERO_ERROR;
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("numeric")),
- isolate->factory()->ToBoolean(
+ factory->NewStringFromStaticAscii("numeric"),
+ factory->ToBoolean(
collator->getAttribute(UCOL_NUMERIC_COLLATION, status) == UCOL_ON),
NONE,
SLOPPY).Assert();
@@ -592,24 +584,24 @@
case UCOL_LOWER_FIRST:
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
- isolate->factory()->NewStringFromAscii(CStrVector("lower")),
+ factory->NewStringFromStaticAscii("caseFirst"),
+ factory->NewStringFromStaticAscii("lower"),
NONE,
SLOPPY).Assert();
break;
case UCOL_UPPER_FIRST:
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
- isolate->factory()->NewStringFromAscii(CStrVector("upper")),
+ factory->NewStringFromStaticAscii("caseFirst"),
+ factory->NewStringFromStaticAscii("upper"),
NONE,
SLOPPY).Assert();
break;
default:
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
- isolate->factory()->NewStringFromAscii(CStrVector("false")),
+ factory->NewStringFromStaticAscii("caseFirst"),
+ factory->NewStringFromStaticAscii("false"),
NONE,
SLOPPY).Assert();
}
@@ -618,8 +610,8 @@
case UCOL_PRIMARY: {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("strength")),
- isolate->factory()->NewStringFromAscii(CStrVector("primary")),
+ factory->NewStringFromStaticAscii("strength"),
+ factory->NewStringFromStaticAscii("primary"),
NONE,
SLOPPY).Assert();
@@ -627,15 +619,15 @@
if (UCOL_ON == collator->getAttribute(UCOL_CASE_LEVEL, status)) {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("case")),
+ factory->NewStringFromStaticAscii("sensitivity"),
+ factory->NewStringFromStaticAscii("case"),
NONE,
SLOPPY).Assert();
} else {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("base")),
+ factory->NewStringFromStaticAscii("sensitivity"),
+ factory->NewStringFromStaticAscii("base"),
NONE,
SLOPPY).Assert();
}
@@ -644,28 +636,28 @@
case UCOL_SECONDARY:
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("strength")),
- isolate->factory()->NewStringFromAscii(CStrVector("secondary")),
+ factory->NewStringFromStaticAscii("strength"),
+ factory->NewStringFromStaticAscii("secondary"),
NONE,
SLOPPY).Assert();
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("accent")),
+ factory->NewStringFromStaticAscii("sensitivity"),
+ factory->NewStringFromStaticAscii("accent"),
NONE,
SLOPPY).Assert();
break;
case UCOL_TERTIARY:
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("strength")),
- isolate->factory()->NewStringFromAscii(CStrVector("tertiary")),
+ factory->NewStringFromStaticAscii("strength"),
+ factory->NewStringFromStaticAscii("tertiary"),
NONE,
SLOPPY).Assert();
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("variant")),
+ factory->NewStringFromStaticAscii("sensitivity"),
+ factory->NewStringFromStaticAscii("variant"),
NONE,
SLOPPY).Assert();
break;
@@ -674,36 +666,36 @@
// put them into variant.
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("strength")),
- isolate->factory()->NewStringFromAscii(CStrVector("quaternary")),
+ factory->NewStringFromStaticAscii("strength"),
+ factory->NewStringFromStaticAscii("quaternary"),
NONE,
SLOPPY).Assert();
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("variant")),
+ factory->NewStringFromStaticAscii("sensitivity"),
+ factory->NewStringFromStaticAscii("variant"),
NONE,
SLOPPY).Assert();
break;
default:
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("strength")),
- isolate->factory()->NewStringFromAscii(CStrVector("identical")),
+ factory->NewStringFromStaticAscii("strength"),
+ factory->NewStringFromStaticAscii("identical"),
NONE,
SLOPPY).Assert();
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("variant")),
+ factory->NewStringFromStaticAscii("sensitivity"),
+ factory->NewStringFromStaticAscii("variant"),
NONE,
SLOPPY).Assert();
}
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("ignorePunctuation")),
- isolate->factory()->ToBoolean(collator->getAttribute(
+ factory->NewStringFromStaticAscii("ignorePunctuation"),
+ factory->ToBoolean(collator->getAttribute(
UCOL_ALTERNATE_HANDLING, status) == UCOL_SHIFTED),
NONE,
SLOPPY).Assert();
@@ -716,16 +708,16 @@
if (U_SUCCESS(status)) {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector(result)),
+ factory->NewStringFromStaticAscii("locale"),
+ factory->NewStringFromAsciiChecked(result),
NONE,
SLOPPY).Assert();
} else {
// This would never happen, since we got the locale from ICU.
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector("und")),
+ factory->NewStringFromStaticAscii("locale"),
+ factory->NewStringFromStaticAscii("und"),
NONE,
SLOPPY).Assert();
}
@@ -769,6 +761,7 @@
const icu::Locale& icu_locale,
icu::BreakIterator* break_iterator,
Handle<JSObject> resolved) {
+ Factory* factory = isolate->factory();
UErrorCode status = U_ZERO_ERROR;
// Set the locale
@@ -779,16 +772,16 @@
if (U_SUCCESS(status)) {
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector(result)),
+ factory->NewStringFromStaticAscii("locale"),
+ factory->NewStringFromAsciiChecked(result),
NONE,
SLOPPY).Assert();
} else {
// This would never happen, since we got the locale from ICU.
JSObject::SetProperty(
resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector("und")),
+ factory->NewStringFromStaticAscii("locale"),
+ factory->NewStringFromStaticAscii("und"),
NONE,
SLOPPY).Assert();
}
@@ -852,7 +845,7 @@
Isolate* isolate,
Handle<JSObject> obj) {
Handle<String> key =
- isolate->factory()->NewStringFromAscii(CStrVector("dateFormat"));
+ isolate->factory()->NewStringFromStaticAscii("dateFormat");
if (JSReceiver::HasLocalProperty(obj, key)) {
return reinterpret_cast<icu::SimpleDateFormat*>(
obj->GetInternalField(0));
@@ -926,7 +919,7 @@
Isolate* isolate,
Handle<JSObject> obj) {
Handle<String> key =
- isolate->factory()->NewStringFromAscii(CStrVector("numberFormat"));
+ isolate->factory()->NewStringFromStaticAscii("numberFormat");
if (JSReceiver::HasLocalProperty(obj, key)) {
return reinterpret_cast<icu::DecimalFormat*>(obj->GetInternalField(0));
}
@@ -981,8 +974,7 @@
icu::Collator* Collator::UnpackCollator(Isolate* isolate,
Handle<JSObject> obj) {
- Handle<String> key =
- isolate->factory()->NewStringFromAscii(CStrVector("collator"));
+ Handle<String> key = isolate->factory()->NewStringFromStaticAscii("collator");
if (JSReceiver::HasLocalProperty(obj, key)) {
return reinterpret_cast<icu::Collator*>(obj->GetInternalField(0));
}
@@ -1041,7 +1033,7 @@
icu::BreakIterator* BreakIterator::UnpackBreakIterator(Isolate* isolate,
Handle<JSObject> obj) {
Handle<String> key =
- isolate->factory()->NewStringFromAscii(CStrVector("breakIterator"));
+ isolate->factory()->NewStringFromStaticAscii("breakIterator");
if (JSReceiver::HasLocalProperty(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 3a4f590..407f93e 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -2703,11 +2703,6 @@
ASSERT(!RelocInfo::IsNone(rmode));
// Don't record external references unless the heap will be serialized.
if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
-#ifdef DEBUG
- if (!Serializer::enabled()) {
- Serializer::TooLateToEnableNow();
- }
-#endif
if (!Serializer::enabled() && !emit_debug_code()) {
return;
}
@@ -2717,16 +2712,17 @@
}
-MaybeObject* Assembler::AllocateConstantPool(Heap* heap) {
+Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
// No out-of-line constant pool support.
- UNREACHABLE();
- return NULL;
+ ASSERT(!FLAG_enable_ool_constant_pool);
+ return isolate->factory()->empty_constant_pool_array();
}
void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
// No out-of-line constant pool support.
- UNREACHABLE();
+ ASSERT(!FLAG_enable_ool_constant_pool);
+ return;
}
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 27e5302..2a8e454 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -1192,7 +1192,7 @@
void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
// Allocate a constant pool of the correct size for the generated code.
- MaybeObject* AllocateConstantPool(Heap* heap);
+ Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
// Generate the constant pool for the generated code.
void PopulateConstantPool(ConstantPoolArray* constant_pool);
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index 785c5fd..12ab3b4 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -949,7 +949,7 @@
// Out of stack space.
__ push(Operand(ebp, 4 * kPointerSize)); // push this
__ push(eax);
- __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
__ bind(&okay);
// End of stack check.
@@ -1252,6 +1252,33 @@
}
+static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
+ Label* stack_overflow) {
+ // ----------- S t a t e -------------
+ // -- eax : actual number of arguments
+ // -- ebx : expected number of arguments
+ // -- edi : function (passed through to callee)
+ // -----------------------------------
+ // Check the stack for overflow. We are not trying to catch
+ // interruptions (e.g. debug break and preemption) here, so the "real stack
+ // limit" is checked.
+ ExternalReference real_stack_limit =
+ ExternalReference::address_of_real_stack_limit(masm->isolate());
+ __ mov(edx, Operand::StaticVariable(real_stack_limit));
+ // Make ecx the space we have left. The stack might already be overflowed
+ // here which will cause ecx to become negative.
+ __ mov(ecx, esp);
+ __ sub(ecx, edx);
+ // Make edx the space we need for the array when it is unrolled onto the
+ // stack.
+ __ mov(edx, ebx);
+ __ shl(edx, kPointerSizeLog2);
+ // Check if the arguments will overflow the stack.
+ __ cmp(ecx, edx);
+ __ j(less_equal, stack_overflow); // Signed comparison.
+}
+
+
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
__ push(ebp);
__ mov(ebp, esp);
@@ -1296,6 +1323,9 @@
Label invoke, dont_adapt_arguments;
__ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
+ Label stack_overflow;
+ ArgumentsAdaptorStackCheck(masm, &stack_overflow);
+
Label enough, too_few;
__ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
__ cmp(eax, ebx);
@@ -1370,6 +1400,14 @@
// -------------------------------------------
__ bind(&dont_adapt_arguments);
__ jmp(edx);
+
+ __ bind(&stack_overflow);
+ {
+ FrameScope frame(masm, StackFrame::MANUAL);
+ EnterArgumentsAdaptorFrame(masm);
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
+ __ int3();
+ }
}
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index dca7ae7..80f3195 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -2584,12 +2584,19 @@
}
-void CEntryStub::GenerateCore(MacroAssembler* masm,
- Label* throw_normal_exception,
- Label* throw_termination_exception,
- bool do_gc,
- bool always_allocate_scope) {
- // eax: result parameter for PerformGC, if any
+void CEntryStub::Generate(MacroAssembler* masm) {
+ // eax: number of arguments including receiver
+ // ebx: pointer to C function (C callee-saved)
+ // ebp: frame pointer (restored after C call)
+ // esp: stack pointer (restored after C call)
+ // esi: current context (C callee-saved)
+ // edi: JS function of the caller (C callee-saved)
+
+ ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
+ // Enter the exit frame that transitions from JavaScript to C++.
+ __ EnterExitFrame(save_doubles_ == kSaveFPRegs);
+
// ebx: pointer to C function (C callee-saved)
// ebp: frame pointer (restored after C call)
// esp: stack pointer (restored after C call)
@@ -2598,67 +2605,44 @@
// Result returned in eax, or eax+edx if result_size_ is 2.
+ Isolate* isolate = masm->isolate();
+
// Check stack alignment.
if (FLAG_debug_code) {
__ CheckStackAlignment();
}
- if (do_gc) {
- // Pass failure code returned from last attempt as first argument to
- // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the
- // stack alignment is known to be correct. This function takes one argument
- // which is passed on the stack, and we know that the stack has been
- // prepared to pass at least one argument.
- __ mov(Operand(esp, 1 * kPointerSize),
- Immediate(ExternalReference::isolate_address(masm->isolate())));
- __ mov(Operand(esp, 0 * kPointerSize), eax); // Result.
- __ call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY);
- }
-
- ExternalReference scope_depth =
- ExternalReference::heap_always_allocate_scope_depth(masm->isolate());
- if (always_allocate_scope) {
- __ inc(Operand::StaticVariable(scope_depth));
- }
-
// Call C function.
__ mov(Operand(esp, 0 * kPointerSize), edi); // argc.
__ mov(Operand(esp, 1 * kPointerSize), esi); // argv.
__ mov(Operand(esp, 2 * kPointerSize),
- Immediate(ExternalReference::isolate_address(masm->isolate())));
+ Immediate(ExternalReference::isolate_address(isolate)));
__ call(ebx);
// Result is in eax or edx:eax - do not destroy these registers!
- if (always_allocate_scope) {
- __ dec(Operand::StaticVariable(scope_depth));
- }
-
// Runtime functions should not return 'the hole'. Allowing it to escape may
// lead to crashes in the IC code later.
if (FLAG_debug_code) {
Label okay;
- __ cmp(eax, masm->isolate()->factory()->the_hole_value());
+ __ cmp(eax, isolate->factory()->the_hole_value());
__ j(not_equal, &okay, Label::kNear);
__ int3();
__ bind(&okay);
}
- // Check for failure result.
- Label failure_returned;
- STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
- __ lea(ecx, Operand(eax, 1));
- // Lower 2 bits of ecx are 0 iff eax has failure tag.
- __ test(ecx, Immediate(kFailureTagMask));
- __ j(zero, &failure_returned);
+ // Check result for exception sentinel.
+ Label exception_returned;
+ __ cmp(eax, isolate->factory()->exception());
+ __ j(equal, &exception_returned);
ExternalReference pending_exception_address(
- Isolate::kPendingExceptionAddress, masm->isolate());
+ Isolate::kPendingExceptionAddress, isolate);
// Check that there is no pending exception, otherwise we
- // should have returned some failure value.
+ // should have returned the exception sentinel.
if (FLAG_debug_code) {
__ push(edx);
- __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value()));
+ __ mov(edx, Immediate(isolate->factory()->the_hole_value()));
Label okay;
__ cmp(edx, Operand::StaticVariable(pending_exception_address));
// Cannot use check here as it attempts to generate call into runtime.
@@ -2672,96 +2656,27 @@
__ LeaveExitFrame(save_doubles_ == kSaveFPRegs);
__ ret(0);
- // Handling of failure.
- __ bind(&failure_returned);
-
- Label retry;
- // If the returned exception is RETRY_AFTER_GC continue at retry label
- STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
- __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
- __ j(zero, &retry, Label::kNear);
+ // Handling of exception.
+ __ bind(&exception_returned);
// Retrieve the pending exception.
__ mov(eax, Operand::StaticVariable(pending_exception_address));
// Clear the pending exception.
- __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value()));
+ __ mov(edx, Immediate(isolate->factory()->the_hole_value()));
__ mov(Operand::StaticVariable(pending_exception_address), edx);
// Special handling of termination exceptions which are uncatchable
// by javascript code.
- __ cmp(eax, masm->isolate()->factory()->termination_exception());
- __ j(equal, throw_termination_exception);
+ Label throw_termination_exception;
+ __ cmp(eax, isolate->factory()->termination_exception());
+ __ j(equal, &throw_termination_exception);
// Handle normal exception.
- __ jmp(throw_normal_exception);
-
- // Retry.
- __ bind(&retry);
-}
-
-
-void CEntryStub::Generate(MacroAssembler* masm) {
- // eax: number of arguments including receiver
- // ebx: pointer to C function (C callee-saved)
- // ebp: frame pointer (restored after C call)
- // esp: stack pointer (restored after C call)
- // esi: current context (C callee-saved)
- // edi: JS function of the caller (C callee-saved)
-
- ProfileEntryHookStub::MaybeCallEntryHook(masm);
-
- // NOTE: Invocations of builtins may return failure objects instead
- // of a proper result. The builtin entry handles this by performing
- // a garbage collection and retrying the builtin (twice).
-
- // Enter the exit frame that transitions from JavaScript to C++.
- __ EnterExitFrame(save_doubles_ == kSaveFPRegs);
-
- // eax: result parameter for PerformGC, if any (setup below)
- // ebx: pointer to builtin function (C callee-saved)
- // ebp: frame pointer (restored after C call)
- // esp: stack pointer (restored after C call)
- // edi: number of arguments including receiver (C callee-saved)
- // esi: argv pointer (C callee-saved)
-
- Label throw_normal_exception;
- Label throw_termination_exception;
-
- // Call into the runtime system.
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- false,
- false);
-
- // Do space-specific GC and retry runtime call.
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- true,
- false);
-
- // Do full GC and retry runtime call one final time.
- Failure* failure = Failure::InternalError();
- __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- true,
- true);
-
- { FrameScope scope(masm, StackFrame::MANUAL);
- __ PrepareCallCFunction(0, eax);
- __ CallCFunction(
- ExternalReference::out_of_memory_function(masm->isolate()), 0);
- }
+ __ Throw(eax);
__ bind(&throw_termination_exception);
__ ThrowUncatchable(eax);
-
- __ bind(&throw_normal_exception);
- __ Throw(eax);
}
@@ -2809,7 +2724,7 @@
ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
masm->isolate());
__ mov(Operand::StaticVariable(pending_exception), eax);
- __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception()));
+ __ mov(eax, Immediate(masm->isolate()->factory()->exception()));
__ jmp(&exit);
// Invoke: Link this frame into the handler chain. There's only one
@@ -3744,198 +3659,6 @@
}
-void ArrayPushStub::Generate(MacroAssembler* masm) {
- int argc = arguments_count();
-
- if (argc == 0) {
- // Noop, return the length.
- __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
- __ ret((argc + 1) * kPointerSize);
- return;
- }
-
- Isolate* isolate = masm->isolate();
-
- if (argc != 1) {
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- Label call_builtin, attempt_to_grow_elements, with_write_barrier;
-
- // Get the elements array of the object.
- __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
-
- if (IsFastSmiOrObjectElementsKind(elements_kind())) {
- // Check that the elements are in fast mode and writable.
- __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
- isolate->factory()->fixed_array_map());
- __ j(not_equal, &call_builtin);
- }
-
- // Get the array's length into eax and calculate new length.
- __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
- STATIC_ASSERT(kSmiTagSize == 1);
- STATIC_ASSERT(kSmiTag == 0);
- __ add(eax, Immediate(Smi::FromInt(argc)));
-
- // Get the elements' length into ecx.
- __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
-
- // Check if we could survive without allocation.
- __ cmp(eax, ecx);
-
- if (IsFastSmiOrObjectElementsKind(elements_kind())) {
- __ j(greater, &attempt_to_grow_elements);
-
- // Check if value is a smi.
- __ mov(ecx, Operand(esp, argc * kPointerSize));
- __ JumpIfNotSmi(ecx, &with_write_barrier);
-
- // Store the value.
- __ mov(FieldOperand(edi, eax, times_half_pointer_size,
- FixedArray::kHeaderSize - argc * kPointerSize),
- ecx);
- } else {
- __ j(greater, &call_builtin);
-
- __ mov(ecx, Operand(esp, argc * kPointerSize));
- __ StoreNumberToDoubleElements(
- ecx, edi, eax, ecx, xmm0, &call_builtin, true, argc * kDoubleSize);
- }
-
- // Save new length.
- __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
- __ ret((argc + 1) * kPointerSize);
-
- if (IsFastDoubleElementsKind(elements_kind())) {
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- __ bind(&with_write_barrier);
-
- if (IsFastSmiElementsKind(elements_kind())) {
- if (FLAG_trace_elements_transitions) __ jmp(&call_builtin);
-
- __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
- isolate->factory()->heap_number_map());
- __ j(equal, &call_builtin);
-
- ElementsKind target_kind = IsHoleyElementsKind(elements_kind())
- ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
- __ mov(ebx, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX));
- __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
- __ mov(ebx, ContextOperand(ebx, Context::JS_ARRAY_MAPS_INDEX));
- const int header_size = FixedArrayBase::kHeaderSize;
- // Verify that the object can be transitioned in place.
- const int origin_offset = header_size + elements_kind() * kPointerSize;
- __ mov(edi, FieldOperand(ebx, origin_offset));
- __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset));
- __ j(not_equal, &call_builtin);
-
- const int target_offset = header_size + target_kind * kPointerSize;
- __ mov(ebx, FieldOperand(ebx, target_offset));
- ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
- masm, DONT_TRACK_ALLOCATION_SITE, NULL);
- // Restore edi used as a scratch register for the write barrier used while
- // setting the map.
- __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
- }
-
- // Save new length.
- __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
-
- // Store the value.
- __ lea(edx, FieldOperand(edi, eax, times_half_pointer_size,
- FixedArray::kHeaderSize - argc * kPointerSize));
- __ mov(Operand(edx, 0), ecx);
-
- __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
-
- __ ret((argc + 1) * kPointerSize);
-
- __ bind(&attempt_to_grow_elements);
- if (!FLAG_inline_new) {
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- __ mov(ebx, Operand(esp, argc * kPointerSize));
- // Growing elements that are SMI-only requires special handling in case the
- // new element is non-Smi. For now, delegate to the builtin.
- if (IsFastSmiElementsKind(elements_kind())) {
- __ JumpIfNotSmi(ebx, &call_builtin);
- }
-
- // We could be lucky and the elements array could be at the top of new-space.
- // In this case we can just grow it in place by moving the allocation pointer
- // up.
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate);
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate);
-
- const int kAllocationDelta = 4;
- ASSERT(kAllocationDelta >= argc);
- // Load top.
- __ mov(ecx, Operand::StaticVariable(new_space_allocation_top));
-
- // Check if it's the end of elements.
- __ lea(edx, FieldOperand(edi, eax, times_half_pointer_size,
- FixedArray::kHeaderSize - argc * kPointerSize));
- __ cmp(edx, ecx);
- __ j(not_equal, &call_builtin);
- __ add(ecx, Immediate(kAllocationDelta * kPointerSize));
- __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
- __ j(above, &call_builtin);
-
- // We fit and could grow elements.
- __ mov(Operand::StaticVariable(new_space_allocation_top), ecx);
-
- // Push the argument...
- __ mov(Operand(edx, 0), ebx);
- // ... and fill the rest with holes.
- for (int i = 1; i < kAllocationDelta; i++) {
- __ mov(Operand(edx, i * kPointerSize),
- isolate->factory()->the_hole_value());
- }
-
- if (IsFastObjectElementsKind(elements_kind())) {
- // We know the elements array is in new space so we don't need the
- // remembered set, but we just pushed a value onto it so we may have to tell
- // the incremental marker to rescan the object that we just grew. We don't
- // need to worry about the holes because they are in old space and already
- // marked black.
- __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
- }
-
- // Restore receiver to edx as finish sequence assumes it's here.
- __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-
- // Increment element's and array's sizes.
- __ add(FieldOperand(edi, FixedArray::kLengthOffset),
- Immediate(Smi::FromInt(kAllocationDelta)));
-
- // NOTE: This only happen in new-space, where we don't care about the
- // black-byte-count on pages. Otherwise we should update that too if the
- // object is black.
-
- __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
- __ ret((argc + 1) * kPointerSize);
-
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
-}
-
-
void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- edx : left
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 5622c30..fbd9a21 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -74,7 +74,7 @@
void EmitPatchInfo() {
if (patch_site_.is_bound()) {
int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
- ASSERT(is_int8(delta_to_patch_site));
+ ASSERT(is_uint8(delta_to_patch_site));
__ test(eax, Immediate(delta_to_patch_site));
#ifdef DEBUG
info_emitted_ = true;
@@ -2227,7 +2227,7 @@
Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->generator_result_map());
+ Handle<Map> map(isolate()->native_context()->iterator_result_map());
__ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT);
__ jmp(&allocated);
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index c2be7da..4a962a6 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -1282,7 +1282,7 @@
Address delta_address = test_instruction_address + 1;
// The delta to the start of the map check instruction and the
// condition code uses at the patched jump.
- int8_t delta = *reinterpret_cast<int8_t*>(delta_address);
+ uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
if (FLAG_trace_ic) {
PrintF("[ patching ic at %p, test=%p, delta=%d\n",
address, test_instruction_address, delta);
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index ebd430c..a7d78d3 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -4406,7 +4406,7 @@
__ test(value, Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr->environment());
- // We know that value is a smi now, so we can omit the check below.
+ // We know now that value is not a smi, so we can omit the check below.
check_needed = OMIT_SMI_CHECK;
}
}
@@ -4497,34 +4497,27 @@
}
-void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) {
- if (FLAG_debug_code && check->hydrogen()->skip_check()) {
+void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
+ Condition cc = instr->hydrogen()->allow_equality() ? above : above_equal;
+ if (instr->index()->IsConstantOperand()) {
+ __ cmp(ToOperand(instr->length()),
+ ToImmediate(LConstantOperand::cast(instr->index()),
+ instr->hydrogen()->length()->representation()));
+ cc = ReverseCondition(cc);
+ } else if (instr->length()->IsConstantOperand()) {
+ __ cmp(ToOperand(instr->index()),
+ ToImmediate(LConstantOperand::cast(instr->length()),
+ instr->hydrogen()->index()->representation()));
+ } else {
+ __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
+ }
+ if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
Label done;
__ j(NegateCondition(cc), &done, Label::kNear);
__ int3();
__ bind(&done);
} else {
- DeoptimizeIf(cc, check->environment());
- }
-}
-
-
-void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
- if (instr->hydrogen()->skip_check() && !FLAG_debug_code) return;
-
- if (instr->index()->IsConstantOperand()) {
- Immediate immediate =
- ToImmediate(LConstantOperand::cast(instr->index()),
- instr->hydrogen()->length()->representation());
- __ cmp(ToOperand(instr->length()), immediate);
- Condition condition =
- instr->hydrogen()->allow_equality() ? below : below_equal;
- ApplyCheckIf(condition, instr);
- } else {
- __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
- Condition condition =
- instr->hydrogen()->allow_equality() ? above : above_equal;
- ApplyCheckIf(condition, instr);
+ DeoptimizeIf(cc, instr->environment());
}
}
@@ -5638,15 +5631,15 @@
__ bind(deferred->check_maps());
}
- UniqueSet<Map> map_set = instr->hydrogen()->map_set();
+ const UniqueSet<Map>* map_set = instr->hydrogen()->map_set();
Label success;
- for (int i = 0; i < map_set.size() - 1; i++) {
- Handle<Map> map = map_set.at(i).handle();
+ for (int i = 0; i < map_set->size() - 1; i++) {
+ Handle<Map> map = map_set->at(i).handle();
__ CompareMap(reg, map);
__ j(equal, &success, Label::kNear);
}
- Handle<Map> map = map_set.at(map_set.size() - 1).handle();
+ Handle<Map> map = map_set->at(map_set->size() - 1).handle();
__ CompareMap(reg, map);
if (instr->hydrogen()->has_migration_target()) {
__ j(not_equal, deferred->entry());
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index b29f0f1..e600ede 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -271,7 +271,6 @@
LEnvironment* environment,
Deoptimizer::BailoutType bailout_type);
void DeoptimizeIf(Condition cc, LEnvironment* environment);
- void ApplyCheckIf(Condition cc, LBoundsCheck* check);
bool DeoptEveryNTimes() {
return FLAG_deopt_every_n_times != 0 && !info()->IsStub();
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index cb15e0d..ffd8d86 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1677,6 +1677,8 @@
LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
HCompareNumericAndBranch* instr) {
+ LInstruction* goto_instr = CheckElideControlInstruction(instr);
+ if (goto_instr != NULL) return goto_instr;
Representation r = instr->representation();
if (r.IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(r));
@@ -1865,9 +1867,16 @@
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
- return AssignEnvironment(new(zone()) LBoundsCheck(
- UseRegisterOrConstantAtStart(instr->index()),
- UseAtStart(instr->length())));
+ if (!FLAG_debug_code && instr->skip_check()) return NULL;
+ LOperand* index = UseRegisterOrConstantAtStart(instr->index());
+ LOperand* length = !index->IsConstantOperand()
+ ? UseOrConstantAtStart(instr->length())
+ : UseAtStart(instr->length());
+ LInstruction* result = new(zone()) LBoundsCheck(index, length);
+ if (!FLAG_debug_code || !instr->skip_check()) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index 255df32..c017cc7 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -1126,7 +1126,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
+ Object* result = Execution::HandleStackGuardInterrupt(isolate);
if (*code_handle != re_code) { // Return address no longer valid
int delta = code_handle->address() - re_code->address();
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 1a745c7..b3bc71c 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -529,6 +529,21 @@
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
+ HeapType* field_type = descriptors->GetFieldType(descriptor);
+ HeapType::Iterator<Map> it = field_type->Classes();
+ if (!it.Done()) {
+ Label do_store;
+ while (true) {
+ __ CompareMap(value_reg, it.Current());
+ it.Advance();
+ if (it.Done()) {
+ __ j(not_equal, miss_label);
+ break;
+ }
+ __ j(equal, &do_store, Label::kNear);
+ }
+ __ bind(&do_store);
+ }
} else if (representation.IsDouble()) {
Label do_store, heap_number;
__ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow);
@@ -699,6 +714,21 @@
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
+ HeapType* field_type = lookup->GetFieldType();
+ HeapType::Iterator<Map> it = field_type->Classes();
+ if (!it.Done()) {
+ Label do_store;
+ while (true) {
+ __ CompareMap(value_reg, it.Current());
+ it.Advance();
+ if (it.Done()) {
+ __ j(not_equal, miss_label);
+ break;
+ }
+ __ j(equal, &do_store, Label::kNear);
+ }
+ __ bind(&do_store);
+ }
} else if (representation.IsDouble()) {
// Load the double storage.
if (index < 0) {
@@ -824,7 +854,8 @@
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
- if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
+ if (type->IsConstant()) current =
+ Handle<JSObject>::cast(type->AsConstant()->Value());
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> holder_map(holder->map());
diff --git a/src/ic.cc b/src/ic.cc
index fef90e4..8d720ea 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -442,7 +442,7 @@
MapHandleList maps;
stub->FindAllMaps(&maps);
if (maps.length() == 1 && stub->IsWeakObjectInIC(*maps.at(0))) {
- maps.at(0)->AddDependentIC(stub);
+ Map::AddDependentIC(maps.at(0), stub);
stub->mark_as_weak_stub();
if (FLAG_enable_ool_constant_pool) {
stub->constant_pool()->set_weak_object_state(
@@ -680,7 +680,8 @@
for (int i = 0; i < number_of_types; i++) {
Handle<HeapType> current_type = types.at(i);
- if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) {
+ if (current_type->IsClass() &&
+ current_type->AsClass()->Map()->is_deprecated()) {
// Filter out deprecated maps to ensure their instances get migrated.
++deprecated_types;
} else if (type->NowIs(current_type)) {
@@ -691,8 +692,8 @@
} else if (handler_to_overwrite == -1 &&
current_type->IsClass() &&
type->IsClass() &&
- IsTransitionOfMonomorphicTarget(*current_type->AsClass(),
- *type->AsClass())) {
+ IsTransitionOfMonomorphicTarget(*current_type->AsClass()->Map(),
+ *type->AsClass()->Map())) {
handler_to_overwrite = i;
}
}
@@ -734,10 +735,11 @@
return isolate->factory()->heap_number_map();
if (type->Is(HeapType::Boolean())) return isolate->factory()->boolean_map();
if (type->IsConstant()) {
- return handle(Handle<JSGlobalObject>::cast(type->AsConstant())->map());
+ return handle(
+ Handle<JSGlobalObject>::cast(type->AsConstant()->Value())->map());
}
ASSERT(type->IsClass());
- return type->AsClass();
+ return type->AsClass()->Map();
}
@@ -1159,7 +1161,7 @@
stub = sloppy_arguments_stub();
} else if (receiver->HasIndexedInterceptor()) {
stub = indexed_interceptor_stub();
- } else if (!key->ToSmi()->IsFailure() &&
+ } else if (!Object::ToSmi(isolate(), key).is_null() &&
(!target().is_identical_to(sloppy_arguments_stub()))) {
stub = LoadElementStub(receiver);
}
@@ -1231,9 +1233,12 @@
ASSERT(!receiver->map()->is_deprecated());
if (!lookup->CanHoldValue(value)) {
Handle<Map> target(lookup->GetTransitionTarget());
+ Representation field_representation = value->OptimalRepresentation();
+ Handle<HeapType> field_type = value->OptimalType(
+ lookup->isolate(), field_representation);
Map::GeneralizeRepresentation(
target, target->LastAdded(),
- value->OptimalRepresentation(), FORCE_FIELD);
+ field_representation, field_type, FORCE_FIELD);
// Lookup the transition again since the transition tree may have changed
// entirely by the migration above.
receiver->map()->LookupTransition(*holder, *name, lookup);
@@ -1650,10 +1655,9 @@
KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
Handle<Object> key,
Handle<Object> value) {
- ASSERT(!key->ToSmi()->IsFailure());
- Smi* smi_key = NULL;
- key->ToSmi()->To(&smi_key);
- int index = smi_key->value();
+ Handle<Object> smi_key = Object::ToSmi(isolate(), key);
+ ASSERT(!smi_key.is_null() && smi_key->IsSmi());
+ int index = Handle<Smi>::cast(smi_key)->value();
bool oob_access = IsOutOfBoundsAccess(receiver, index);
// Don't consider this a growing store if the store would send the receiver to
// dictionary mode.
@@ -1775,7 +1779,7 @@
if (object->IsJSObject()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
- bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure();
+ bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null();
if (receiver->elements()->map() ==
isolate()->heap()->sloppy_arguments_elements_map()) {
if (strict_mode() == SLOPPY) {
@@ -1827,7 +1831,7 @@
// Used from ic-<arch>.cc.
// Used from ic-<arch>.cc.
-RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
+RUNTIME_FUNCTION(LoadIC_Miss) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
@@ -1841,7 +1845,7 @@
// Used from ic-<arch>.cc
-RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
+RUNTIME_FUNCTION(KeyedLoadIC_Miss) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
@@ -1854,7 +1858,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) {
+RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
@@ -1868,7 +1872,7 @@
// Used from ic-<arch>.cc.
-RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
+RUNTIME_FUNCTION(StoreIC_Miss) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
@@ -1884,7 +1888,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) {
+RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
@@ -1900,7 +1904,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
+RUNTIME_FUNCTION(StoreIC_ArrayLength) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -1926,7 +1930,7 @@
// Extend storage is called in a store inline cache when
// it is necessary to extend the properties array of a
// JSObject.
-RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) {
+RUNTIME_FUNCTION(SharedStoreIC_ExtendStorage) {
HandleScope shs(isolate);
ASSERT(args.length() == 3);
@@ -1967,7 +1971,7 @@
// Used from ic-<arch>.cc.
-RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
+RUNTIME_FUNCTION(KeyedStoreIC_Miss) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
@@ -1983,7 +1987,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) {
+RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
@@ -1999,7 +2003,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) {
+RUNTIME_FUNCTION(StoreIC_Slow) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
@@ -2016,7 +2020,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
+RUNTIME_FUNCTION(KeyedStoreIC_Slow) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
@@ -2033,7 +2037,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) {
+RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
@@ -2552,7 +2556,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) {
+RUNTIME_FUNCTION(BinaryOpIC_Miss) {
HandleScope scope(isolate);
ASSERT_EQ(2, args.length());
Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft);
@@ -2567,7 +2571,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite) {
+RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite) {
HandleScope scope(isolate);
ASSERT_EQ(3, args.length());
Handle<AllocationSite> allocation_site = args.at<AllocationSite>(
@@ -2800,7 +2804,7 @@
// Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
-RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
+RUNTIME_FUNCTION(CompareIC_Miss) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
@@ -2862,7 +2866,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss) {
+RUNTIME_FUNCTION(CompareNilIC_Miss) {
HandleScope scope(isolate);
Handle<Object> object = args.at<Object>(0);
CompareNilIC ic(isolate);
@@ -2870,7 +2874,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Unreachable) {
+RUNTIME_FUNCTION(Unreachable) {
UNREACHABLE();
CHECK(false);
return isolate->heap()->undefined_value();
@@ -2927,7 +2931,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) {
+RUNTIME_FUNCTION(ToBooleanIC_Miss) {
ASSERT(args.length() == 1);
HandleScope scope(isolate);
Handle<Object> object = args.at<Object>(0);
diff --git a/src/ic.h b/src/ic.h
index ea074ca..dd6b609 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -969,15 +969,15 @@
enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss);
+DECLARE_RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure);
+DECLARE_RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure);
+DECLARE_RUNTIME_FUNCTION(UnaryOpIC_Miss);
+DECLARE_RUNTIME_FUNCTION(StoreIC_MissFromStubFailure);
+DECLARE_RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss);
+DECLARE_RUNTIME_FUNCTION(BinaryOpIC_Miss);
+DECLARE_RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite);
+DECLARE_RUNTIME_FUNCTION(CompareNilIC_Miss);
+DECLARE_RUNTIME_FUNCTION(ToBooleanIC_Miss);
} } // namespace v8::internal
diff --git a/src/isolate.cc b/src/isolate.cc
index 0c108fb..9a5bc5a 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -212,37 +212,6 @@
}
} static_initializer;
-#ifdef ENABLE_DEBUGGER_SUPPORT
-Debugger* Isolate::GetDefaultIsolateDebugger() {
- EnsureDefaultIsolate();
- return default_isolate_->debugger();
-}
-#endif
-
-
-StackGuard* Isolate::GetDefaultIsolateStackGuard() {
- EnsureDefaultIsolate();
- return default_isolate_->stack_guard();
-}
-
-
-void Isolate::EnterDefaultIsolate() {
- EnsureDefaultIsolate();
- ASSERT(default_isolate_ != NULL);
-
- PerIsolateThreadData* data = CurrentPerIsolateThreadData();
- // If not yet in default isolate - enter it.
- if (data == NULL || data->isolate() != default_isolate_) {
- default_isolate_->Enter();
- }
-}
-
-
-v8::Isolate* Isolate::GetDefaultIsolateForLocking() {
- EnsureDefaultIsolate();
- return reinterpret_cast<v8::Isolate*>(default_isolate_);
-}
-
Address Isolate::get_address_from_id(Isolate::AddressId id) {
return isolate_addresses_[id];
@@ -550,7 +519,7 @@
if (options & StackTrace::kLineNumber) {
int script_line_offset = script->line_offset()->value();
int position = frames[i].code()->SourcePosition(frames[i].pc());
- int line_number = GetScriptLineNumber(script, position);
+ int line_number = Script::GetLineNumber(script, position);
// line_number is already shifted by the script_line_offset.
int relative_line_number = line_number - script_line_offset;
if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
@@ -585,7 +554,7 @@
}
if (options & StackTrace::kScriptNameOrSourceURL) {
- Handle<Object> result = GetScriptNameOrSourceURL(script);
+ Handle<Object> result = Script::GetNameOrSourceURL(script);
JSObject::SetLocalPropertyIgnoreAttributes(
stack_frame, script_name_or_source_url_key, result, NONE).Check();
}
@@ -838,7 +807,7 @@
"Uncaught RangeError: Maximum call stack size exceeded";
-Failure* Isolate::StackOverflow() {
+Object* Isolate::StackOverflow() {
HandleScope scope(this);
// At this point we cannot create an Error object using its javascript
// constructor. Instead, we copy the pre-constructed boilerplate and
@@ -850,9 +819,9 @@
DoThrow(*exception, NULL);
// Get stack trace limit.
- Handle<Object> error =
- GetProperty(js_builtins_object(), "$Error").ToHandleChecked();
- if (!error->IsJSObject()) return Failure::Exception();
+ Handle<Object> error = Object::GetProperty(
+ this, js_builtins_object(), "$Error").ToHandleChecked();
+ if (!error->IsJSObject()) return heap()->exception();
Handle<String> stackTraceLimit =
factory()->InternalizeUtf8String("stackTraceLimit");
@@ -860,7 +829,7 @@
Handle<Object> stack_trace_limit =
JSObject::GetDataProperty(Handle<JSObject>::cast(error),
stackTraceLimit);
- if (!stack_trace_limit->IsNumber()) return Failure::Exception();
+ if (!stack_trace_limit->IsNumber()) return heap()->exception();
double dlimit = stack_trace_limit->Number();
int limit = std::isnan(dlimit) ? 0 : static_cast<int>(dlimit);
@@ -869,13 +838,13 @@
JSObject::SetHiddenProperty(exception,
factory()->hidden_stack_trace_string(),
stack_trace);
- return Failure::Exception();
+ return heap()->exception();
}
-Failure* Isolate::TerminateExecution() {
+Object* Isolate::TerminateExecution() {
DoThrow(heap_.termination_exception(), NULL);
- return Failure::Exception();
+ return heap()->exception();
}
@@ -896,13 +865,13 @@
}
-Failure* Isolate::Throw(Object* exception, MessageLocation* location) {
+Object* Isolate::Throw(Object* exception, MessageLocation* location) {
DoThrow(exception, location);
- return Failure::Exception();
+ return heap()->exception();
}
-Failure* Isolate::ReThrow(Object* exception) {
+Object* Isolate::ReThrow(Object* exception) {
bool can_be_caught_externally = false;
bool catchable_by_javascript = is_catchable_by_javascript(exception);
ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
@@ -912,18 +881,17 @@
// Set the exception being re-thrown.
set_pending_exception(exception);
- if (exception->IsFailure()) return exception->ToFailureUnchecked();
- return Failure::Exception();
+ return heap()->exception();
}
-Failure* Isolate::ThrowIllegalOperation() {
+Object* Isolate::ThrowIllegalOperation() {
if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
return Throw(heap_.illegal_access_string());
}
-Failure* Isolate::ThrowInvalidStringLength() {
+Object* Isolate::ThrowInvalidStringLength() {
return Throw(*factory()->NewRangeError(
"invalid_string_length", HandleVector<Object>(NULL, 0)));
}
@@ -958,7 +926,7 @@
}
-Failure* Isolate::PromoteScheduledException() {
+Object* Isolate::PromoteScheduledException() {
Object* thrown = scheduled_exception();
clear_scheduled_exception();
// Re-throw the exception to avoid getting repeated error reporting.
@@ -1169,19 +1137,19 @@
// In this case we could have an extension (or an internal error
// somewhere) and we print out the line number at which the error occured
// to the console for easier debugging.
- int line_number = GetScriptLineNumberSafe(location->script(),
- location->start_pos());
+ int line_number =
+ location->script()->GetLineNumber(location->start_pos()) + 1;
if (exception->IsString() && location->script()->name()->IsString()) {
OS::PrintError(
"Extension or internal compilation error: %s in %s at line %d.\n",
String::cast(exception)->ToCString().get(),
String::cast(location->script()->name())->ToCString().get(),
- line_number + 1);
+ line_number);
} else if (location->script()->name()->IsString()) {
OS::PrintError(
"Extension or internal compilation error in %s at line %d.\n",
String::cast(location->script()->name())->ToCString().get(),
- line_number + 1);
+ line_number);
} else {
OS::PrintError("Extension or internal compilation error.\n");
}
@@ -1248,7 +1216,7 @@
HandleScope scope(this);
if (thread_local_top_.pending_exception_ ==
- heap()->termination_exception()) {
+ heap()->termination_exception()) {
// Do nothing: if needed, the exception has been already propagated to
// v8::TryCatch.
} else {
@@ -1690,10 +1658,7 @@
// Has to be called while counters_ are still alive
runtime_zone_.DeleteKeptSegment();
- // The entry stack must be empty when we get here,
- // except for the default isolate, where it can
- // still contain up to one entry stack item
- ASSERT(entry_stack_ == NULL || this == default_isolate_);
+ // The entry stack must be empty when we get here.
ASSERT(entry_stack_ == NULL || entry_stack_->previous_item == NULL);
delete entry_stack_;
diff --git a/src/isolate.h b/src/isolate.h
index 3801901..418c22f 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -117,7 +117,7 @@
// of handles to the actual constants.
typedef ZoneList<Handle<Object> > ZoneObjectList;
-#define RETURN_IF_SCHEDULED_EXCEPTION(isolate) \
+#define RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate) \
do { \
Isolate* __isolate__ = (isolate); \
if (__isolate__->has_scheduled_exception()) { \
@@ -125,33 +125,6 @@
} \
} while (false)
-#define RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, T) \
- do { \
- Isolate* __isolate__ = (isolate); \
- if (__isolate__->has_scheduled_exception()) { \
- __isolate__->PromoteScheduledException(); \
- return Handle<T>::null(); \
- } \
- } while (false)
-
-#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value) \
- do { \
- if ((call).is_null()) { \
- ASSERT((isolate)->has_pending_exception()); \
- return (value); \
- } \
- } while (false)
-
-#define CHECK_NOT_EMPTY_HANDLE(isolate, call) \
- do { \
- ASSERT(!(isolate)->has_pending_exception()); \
- CHECK(!(call).is_null()); \
- } while (false)
-
-#define RETURN_IF_EMPTY_HANDLE(isolate, call) \
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, Failure::Exception())
-
-
// Macros for MaybeHandle.
#define RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, T) \
@@ -172,7 +145,8 @@
} while (false)
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call) \
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, Failure::Exception())
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE( \
+ isolate, dst, call, isolate->heap()->exception())
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T) \
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, MaybeHandle<T>())
@@ -186,7 +160,7 @@
} while (false)
#define RETURN_FAILURE_ON_EXCEPTION(isolate, call) \
- RETURN_ON_EXCEPTION_VALUE(isolate, call, Failure::Exception())
+ RETURN_ON_EXCEPTION_VALUE(isolate, call, isolate->heap()->exception())
#define RETURN_ON_EXCEPTION(isolate, call, T) \
RETURN_ON_EXCEPTION_VALUE(isolate, call, MaybeHandle<T>())
@@ -556,16 +530,6 @@
// If one does not yet exist, return null.
PerIsolateThreadData* FindPerThreadDataForThread(ThreadId thread_id);
-#ifdef ENABLE_DEBUGGER_SUPPORT
- // Get the debugger from the default isolate. Preinitializes the
- // default isolate if needed.
- static Debugger* GetDefaultIsolateDebugger();
-#endif
-
- // Get the stack guard from the default isolate. Preinitializes the
- // default isolate if needed.
- static StackGuard* GetDefaultIsolateStackGuard();
-
// Returns the key used to store the pointer to the current isolate.
// Used internally for V8 threads that do not execute JavaScript but still
// are part of the domain of an isolate (like the context switcher).
@@ -580,12 +544,6 @@
static Thread::LocalStorageKey per_isolate_thread_data_key();
- // If a client attempts to create a Locker without specifying an isolate,
- // we assume that the client is using legacy behavior. Set up the current
- // thread to be inside the implicit isolate (or fail a check if we have
- // switched to non-legacy behavior).
- static void EnterDefaultIsolate();
-
// Mutex for serializing access to break control structures.
RecursiveMutex* break_access() { return &break_access_; }
@@ -610,17 +568,17 @@
// Interface to pending exception.
Object* pending_exception() {
ASSERT(has_pending_exception());
- ASSERT(!thread_local_top_.pending_exception_->IsFailure());
+ ASSERT(!thread_local_top_.pending_exception_->IsException());
return thread_local_top_.pending_exception_;
}
- void set_pending_exception(Object* exception) {
- ASSERT(!exception->IsFailure());
- thread_local_top_.pending_exception_ = exception;
+ void set_pending_exception(Object* exception_obj) {
+ ASSERT(!exception_obj->IsException());
+ thread_local_top_.pending_exception_ = exception_obj;
}
void clear_pending_exception() {
- ASSERT(!thread_local_top_.pending_exception_->IsFailure());
+ ASSERT(!thread_local_top_.pending_exception_->IsException());
thread_local_top_.pending_exception_ = heap_.the_hole_value();
}
@@ -629,7 +587,7 @@
}
bool has_pending_exception() {
- ASSERT(!thread_local_top_.pending_exception_->IsFailure());
+ ASSERT(!thread_local_top_.pending_exception_->IsException());
return !thread_local_top_.pending_exception_->IsTheHole();
}
@@ -671,15 +629,15 @@
Object* scheduled_exception() {
ASSERT(has_scheduled_exception());
- ASSERT(!thread_local_top_.scheduled_exception_->IsFailure());
+ ASSERT(!thread_local_top_.scheduled_exception_->IsException());
return thread_local_top_.scheduled_exception_;
}
bool has_scheduled_exception() {
- ASSERT(!thread_local_top_.scheduled_exception_->IsFailure());
+ ASSERT(!thread_local_top_.scheduled_exception_->IsException());
return thread_local_top_.scheduled_exception_ != heap_.the_hole_value();
}
void clear_scheduled_exception() {
- ASSERT(!thread_local_top_.scheduled_exception_->IsFailure());
+ ASSERT(!thread_local_top_.scheduled_exception_->IsException());
thread_local_top_.scheduled_exception_ = heap_.the_hole_value();
}
@@ -797,7 +755,7 @@
// Exception throwing support. The caller should use the result
// of Throw() as its return value.
- Failure* Throw(Object* exception, MessageLocation* location = NULL);
+ Object* Throw(Object* exception, MessageLocation* location = NULL);
template <typename T>
MUST_USE_RESULT MaybeHandle<T> Throw(Handle<Object> exception,
@@ -809,7 +767,7 @@
// Re-throw an exception. This involves no error reporting since
// error reporting was handled when the exception was thrown
// originally.
- Failure* ReThrow(Object* exception);
+ Object* ReThrow(Object* exception);
void ScheduleThrow(Object* exception);
// Re-set pending message, script and positions reported to the TryCatch
// back to the TLS for re-use when rethrowing.
@@ -817,11 +775,11 @@
void ReportPendingMessages();
// Return pending location if any or unfilled structure.
MessageLocation GetMessageLocation();
- Failure* ThrowIllegalOperation();
- Failure* ThrowInvalidStringLength();
+ Object* ThrowIllegalOperation();
+ Object* ThrowInvalidStringLength();
// Promote a scheduled exception to pending. Asserts has_scheduled_exception.
- Failure* PromoteScheduledException();
+ Object* PromoteScheduledException();
void DoThrow(Object* exception, MessageLocation* location);
// Checks if exception should be reported and finds out if it's
// caught externally.
@@ -833,8 +791,8 @@
void ComputeLocation(MessageLocation* target);
// Out of resource exception helpers.
- Failure* StackOverflow();
- Failure* TerminateExecution();
+ Object* StackOverflow();
+ Object* TerminateExecution();
void CancelTerminateExecution();
// Administration
@@ -1124,11 +1082,6 @@
return sweeper_thread_;
}
- // PreInits and returns a default isolate. Needed when a new thread tries
- // to create a Locker for the first time (the lock itself is in the isolate).
- // TODO(svenpanne) This method is on death row...
- static v8::Isolate* GetDefaultIsolateForLocking();
-
int id() const { return static_cast<int>(id_); }
HStatistics* GetHStatistics();
diff --git a/src/json-parser.h b/src/json-parser.h
index a7dbd3a..8c19bc8 100644
--- a/src/json-parser.h
+++ b/src/json-parser.h
@@ -415,7 +415,15 @@
if (value->IsSmi() && expected_representation.IsDouble()) {
value = factory()->NewHeapNumber(
Handle<Smi>::cast(value)->value());
+ } else if (expected_representation.IsHeapObject() &&
+ !target->instance_descriptors()->GetFieldType(
+ descriptor)->NowContains(value)) {
+ Handle<HeapType> value_type(value->OptimalType(
+ isolate(), expected_representation));
+ Map::GeneralizeFieldType(target, descriptor, value_type);
}
+ ASSERT(target->instance_descriptors()->GetFieldType(
+ descriptor)->NowContains(value));
properties.Add(value, zone());
map = target;
continue;
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index c4f6b1f..947a396 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -39,17 +39,18 @@
public:
explicit BasicJsonStringifier(Isolate* isolate);
- MaybeObject* Stringify(Handle<Object> object);
+ MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object);
- INLINE(static MaybeObject* StringifyString(Isolate* isolate,
- Handle<String> object));
+ MUST_USE_RESULT INLINE(static MaybeHandle<Object> StringifyString(
+ Isolate* isolate,
+ Handle<String> object));
private:
static const int kInitialPartLength = 32;
static const int kMaxPartLength = 16 * 1024;
static const int kPartLengthGrowthFactor = 2;
- enum Result { UNCHANGED, SUCCESS, EXCEPTION, CIRCULAR, STACK_OVERFLOW };
+ enum Result { UNCHANGED, SUCCESS, EXCEPTION };
void Accumulate();
@@ -91,9 +92,9 @@
bool deferred_key);
template <typename ResultType, typename Char>
- INLINE(static MaybeObject* StringifyString_(Isolate* isolate,
- Vector<Char> vector,
- Handle<String> result));
+ INLINE(static Handle<String> StringifyString_(Isolate* isolate,
+ Vector<Char> vector,
+ Handle<String> result));
// Entry point to serialize the object.
INLINE(Result SerializeObject(Handle<Object> obj)) {
@@ -141,7 +142,7 @@
INLINE(Result SerializeJSArray(Handle<JSArray> object));
INLINE(Result SerializeJSObject(Handle<JSObject> object));
- Result SerializeJSArraySlow(Handle<JSArray> object, int length);
+ Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t length);
void SerializeString(Handle<String> object);
@@ -272,29 +273,25 @@
}
-MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) {
- switch (SerializeObject(object)) {
- case UNCHANGED:
- return isolate_->heap()->undefined_value();
- case SUCCESS: {
- ShrinkCurrentPart();
- Accumulate();
- if (overflowed_) return isolate_->ThrowInvalidStringLength();
- return *accumulator();
+MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) {
+ Result result = SerializeObject(object);
+ if (result == UNCHANGED) return isolate_->factory()->undefined_value();
+ if (result == SUCCESS) {
+ ShrinkCurrentPart();
+ Accumulate();
+ if (overflowed_) {
+ return isolate_->Throw<Object>(
+ isolate_->factory()->NewInvalidStringLengthError());
}
- case CIRCULAR:
- return isolate_->Throw(*factory_->NewTypeError(
- "circular_structure", HandleVector<Object>(NULL, 0)));
- case STACK_OVERFLOW:
- return isolate_->StackOverflow();
- default:
- return Failure::Exception();
+ return accumulator();
}
+ ASSERT(result == EXCEPTION);
+ return MaybeHandle<Object>();
}
-MaybeObject* BasicJsonStringifier::StringifyString(Isolate* isolate,
- Handle<String> object) {
+MaybeHandle<Object> BasicJsonStringifier::StringifyString(
+ Isolate* isolate, Handle<String> object) {
static const int kJsonQuoteWorstCaseBlowup = 6;
static const int kSpaceForQuotes = 2;
int worst_case_length =
@@ -328,9 +325,9 @@
template <typename ResultType, typename Char>
-MaybeObject* BasicJsonStringifier::StringifyString_(Isolate* isolate,
- Vector<Char> vector,
- Handle<String> result) {
+Handle<String> BasicJsonStringifier::StringifyString_(Isolate* isolate,
+ Vector<Char> vector,
+ Handle<String> result) {
DisallowHeapAllocation no_gc;
int final_size = 0;
ResultType* dest = ResultType::cast(*result);
@@ -339,7 +336,7 @@
dest->GetChars() + 1,
vector.length());
dest->Set(final_size++, '\"');
- return *SeqString::Truncate(Handle<SeqString>::cast(result), final_size);
+ return SeqString::Truncate(Handle<SeqString>::cast(result), final_size);
}
@@ -390,7 +387,10 @@
BasicJsonStringifier::Result BasicJsonStringifier::StackPush(
Handle<Object> object) {
StackLimitCheck check(isolate_);
- if (check.HasOverflowed()) return STACK_OVERFLOW;
+ if (check.HasOverflowed()) {
+ isolate_->StackOverflow();
+ return EXCEPTION;
+ }
int length = Smi::cast(stack_->length())->value();
{
@@ -398,7 +398,10 @@
FixedArray* elements = FixedArray::cast(stack_->elements());
for (int i = 0; i < length; i++) {
if (elements->get(i) == *object) {
- return CIRCULAR;
+ AllowHeapAllocation allow_to_return_error;
+ isolate_->Throw(*factory_->NewTypeError(
+ "circular_structure", HandleVector<Object>(NULL, 0)));
+ return EXCEPTION;
}
}
}
@@ -481,9 +484,9 @@
Handle<Object> key,
bool deferred_comma,
bool deferred_key) {
- Handle<JSObject> builtins(isolate_->native_context()->builtins());
- Handle<JSFunction> builtin = Handle<JSFunction>::cast(
- GetProperty(builtins, "JSONSerializeAdapter").ToHandleChecked());
+ Handle<JSObject> builtins(isolate_->native_context()->builtins(), isolate_);
+ Handle<JSFunction> builtin = Handle<JSFunction>::cast(Object::GetProperty(
+ isolate_, builtins, "JSONSerializeAdapter").ToHandleChecked());
Handle<Object> argv[] = { key, object };
Handle<Object> result;
@@ -566,13 +569,14 @@
HandleScope handle_scope(isolate_);
Result stack_push = StackPush(object);
if (stack_push != SUCCESS) return stack_push;
- int length = Smi::cast(object->length())->value();
+ uint32_t length = 0;
+ CHECK(object->length()->ToArrayIndex(&length));
Append('[');
switch (object->GetElementsKind()) {
case FAST_SMI_ELEMENTS: {
Handle<FixedArray> elements(
FixedArray::cast(object->elements()), isolate_);
- for (int i = 0; i < length; i++) {
+ for (uint32_t i = 0; i < length; i++) {
if (i > 0) Append(',');
SerializeSmi(Smi::cast(elements->get(i)));
}
@@ -581,7 +585,7 @@
case FAST_DOUBLE_ELEMENTS: {
Handle<FixedDoubleArray> elements(
FixedDoubleArray::cast(object->elements()), isolate_);
- for (int i = 0; i < length; i++) {
+ for (uint32_t i = 0; i < length; i++) {
if (i > 0) Append(',');
SerializeDouble(elements->get_scalar(i));
}
@@ -590,7 +594,7 @@
case FAST_ELEMENTS: {
Handle<FixedArray> elements(
FixedArray::cast(object->elements()), isolate_);
- for (int i = 0; i < length; i++) {
+ for (uint32_t i = 0; i < length; i++) {
if (i > 0) Append(',');
Result result =
SerializeElement(isolate_,
@@ -622,8 +626,8 @@
BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow(
- Handle<JSArray> object, int length) {
- for (int i = 0; i < length; i++) {
+ Handle<JSArray> object, uint32_t length) {
+ for (uint32_t i = 0; i < length; i++) {
if (i > 0) Append(',');
Handle<Object> element;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
@@ -686,13 +690,13 @@
}
Result result = SerializeProperty(property, comma, key);
if (!comma && result == SUCCESS) comma = true;
- if (result >= EXCEPTION) return result;
+ if (result == EXCEPTION) return result;
}
} else {
Handle<FixedArray> contents;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate_, contents,
- GetKeysInFixedArrayFor(object, LOCAL_ONLY),
+ JSReceiver::GetKeys(object, JSReceiver::LOCAL_ONLY),
EXCEPTION);
for (int i = 0; i < contents->length(); i++) {
@@ -720,7 +724,7 @@
isolate_, property, maybe_property, EXCEPTION);
Result result = SerializeProperty(property, comma, key_handle);
if (!comma && result == SUCCESS) comma = true;
- if (result >= EXCEPTION) return result;
+ if (result == EXCEPTION) return result;
}
}
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 35b3996..2ab2d27 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -95,10 +95,12 @@
}
-static inline void ThrowRegExpException(Handle<JSRegExp> re,
- Handle<String> pattern,
- Handle<String> error_text,
- const char* message) {
+MUST_USE_RESULT
+static inline MaybeHandle<Object> ThrowRegExpException(
+ Handle<JSRegExp> re,
+ Handle<String> pattern,
+ Handle<String> error_text,
+ const char* message) {
Isolate* isolate = re->GetIsolate();
Factory* factory = isolate->factory();
Handle<FixedArray> elements = factory->NewFixedArray(2);
@@ -106,7 +108,7 @@
elements->set(1, *error_text);
Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
Handle<Object> regexp_err = factory->NewSyntaxError(message, array);
- isolate->Throw(*regexp_err);
+ return isolate->Throw<Object>(regexp_err);
}
@@ -167,9 +169,9 @@
// Generic RegExp methods. Dispatches to implementation specific methods.
-Handle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
- Handle<String> pattern,
- Handle<String> flag_str) {
+MaybeHandle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
+ Handle<String> pattern,
+ Handle<String> flag_str) {
Isolate* isolate = re->GetIsolate();
Zone zone(isolate);
JSRegExp::Flags flags = RegExpFlagsFromString(flag_str);
@@ -192,11 +194,10 @@
if (!RegExpParser::ParseRegExp(&reader, flags.is_multiline(),
&parse_result, &zone)) {
// Throw an exception if we fail to parse the pattern.
- ThrowRegExpException(re,
- pattern,
- parse_result.error,
- "malformed_regexp");
- return Handle<Object>::null();
+ return ThrowRegExpException(re,
+ pattern,
+ parse_result.error,
+ "malformed_regexp");
}
bool has_been_compiled = false;
@@ -212,8 +213,11 @@
parse_result.capture_count == 0) {
RegExpAtom* atom = parse_result.tree->AsAtom();
Vector<const uc16> atom_pattern = atom->data();
- Handle<String> atom_string =
- isolate->factory()->NewStringFromTwoByte(atom_pattern);
+ Handle<String> atom_string;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, atom_string,
+ isolate->factory()->NewStringFromTwoByte(atom_pattern),
+ Object);
if (!HasFewDifferentCharacters(atom_string)) {
AtomCompile(re, pattern, flags, atom_string);
has_been_compiled = true;
@@ -232,23 +236,19 @@
}
-Handle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp,
- Handle<String> subject,
- int index,
- Handle<JSArray> last_match_info) {
+MaybeHandle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp,
+ Handle<String> subject,
+ int index,
+ Handle<JSArray> last_match_info) {
switch (regexp->TypeTag()) {
case JSRegExp::ATOM:
return AtomExec(regexp, subject, index, last_match_info);
case JSRegExp::IRREGEXP: {
- Handle<Object> result =
- IrregexpExec(regexp, subject, index, last_match_info);
- ASSERT(!result.is_null() ||
- regexp->GetIsolate()->has_pending_exception());
- return result;
+ return IrregexpExec(regexp, subject, index, last_match_info);
}
default:
UNREACHABLE();
- return Handle<Object>::null();
+ return MaybeHandle<Object>();
}
}
@@ -448,10 +448,10 @@
&zone)) {
// Throw an exception if we fail to parse the pattern.
// THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once.
- ThrowRegExpException(re,
- pattern,
- compile_data.error,
- "malformed_regexp");
+ USE(ThrowRegExpException(re,
+ pattern,
+ compile_data.error,
+ "malformed_regexp"));
return false;
}
RegExpEngine::CompilationResult result =
@@ -465,9 +465,8 @@
&zone);
if (result.error_message != NULL) {
// Unable to compile regexp.
- Handle<String> error_message =
- isolate->factory()->NewStringFromUtf8(CStrVector(result.error_message));
- ASSERT(!error_message.is_null());
+ Handle<String> error_message = isolate->factory()->NewStringFromUtf8(
+ CStrVector(result.error_message)).ToHandleChecked();
CreateRegExpErrorObjectAndThrow(re, is_ascii, error_message, isolate);
return false;
}
@@ -638,10 +637,10 @@
}
-Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp,
- Handle<String> subject,
- int previous_index,
- Handle<JSArray> last_match_info) {
+MaybeHandle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp,
+ Handle<String> subject,
+ int previous_index,
+ Handle<JSArray> last_match_info) {
Isolate* isolate = regexp->GetIsolate();
ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
@@ -657,7 +656,7 @@
if (required_registers < 0) {
// Compiling failed with an exception.
ASSERT(isolate->has_pending_exception());
- return Handle<Object>::null();
+ return MaybeHandle<Object>();
}
int32_t* output_registers = NULL;
@@ -679,7 +678,7 @@
}
if (res == RE_EXCEPTION) {
ASSERT(isolate->has_pending_exception());
- return Handle<Object>::null();
+ return MaybeHandle<Object>();
}
ASSERT(res == RE_FAILURE);
return isolate->factory()->null_value();
diff --git a/src/jsregexp.h b/src/jsregexp.h
index a0b526b..364cb91 100644
--- a/src/jsregexp.h
+++ b/src/jsregexp.h
@@ -69,16 +69,18 @@
// generic data and choice of implementation - as well as what
// the implementation wants to store in the data field.
// Returns false if compilation fails.
- static Handle<Object> Compile(Handle<JSRegExp> re,
- Handle<String> pattern,
- Handle<String> flags);
+ MUST_USE_RESULT static MaybeHandle<Object> Compile(
+ Handle<JSRegExp> re,
+ Handle<String> pattern,
+ Handle<String> flags);
// See ECMA-262 section 15.10.6.2.
// This function calls the garbage collector if necessary.
- static Handle<Object> Exec(Handle<JSRegExp> regexp,
- Handle<String> subject,
- int index,
- Handle<JSArray> lastMatchInfo);
+ MUST_USE_RESULT static MaybeHandle<Object> Exec(
+ Handle<JSRegExp> regexp,
+ Handle<String> subject,
+ int index,
+ Handle<JSArray> lastMatchInfo);
// Prepares a JSRegExp object with Irregexp-specific data.
static void IrregexpInitialize(Handle<JSRegExp> re,
@@ -133,10 +135,11 @@
// On a successful match, the result is a JSArray containing
// captured positions. On a failure, the result is the null value.
// Returns an empty handle in case of an exception.
- static Handle<Object> IrregexpExec(Handle<JSRegExp> regexp,
- Handle<String> subject,
- int index,
- Handle<JSArray> lastMatchInfo);
+ MUST_USE_RESULT static MaybeHandle<Object> IrregexpExec(
+ Handle<JSRegExp> regexp,
+ Handle<String> subject,
+ int index,
+ Handle<JSArray> lastMatchInfo);
// Set last match info. If match is NULL, then setting captures is omitted.
static Handle<JSArray> SetLastMatchInfo(Handle<JSArray> last_match_info,
diff --git a/src/lazy-instance.h b/src/lazy-instance.h
index fc03f4d..ccf8b66 100644
--- a/src/lazy-instance.h
+++ b/src/lazy-instance.h
@@ -66,8 +66,8 @@
// LAZY_INSTANCE_INITIALIZER;
//
// WARNINGS:
-// - This implementation of LazyInstance is NOT THREAD-SAFE by default. See
-// ThreadSafeInitOnceTrait declared below for that.
+// - This implementation of LazyInstance IS THREAD-SAFE by default. See
+// SingleThreadInitOnceTrait if you don't care about thread safety.
// - Lazy initialization comes with a cost. Make sure that you don't use it on
// critical path. Consider adding your initialization code to a function
// which is explicitly called once.
@@ -227,7 +227,7 @@
template <typename T,
typename CreateTrait = DefaultConstructTrait<T>,
- typename InitOnceTrait = SingleThreadInitOnceTrait,
+ typename InitOnceTrait = ThreadSafeInitOnceTrait,
typename DestroyTrait = LeakyInstanceTrait<T> >
struct LazyStaticInstance {
typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>,
@@ -237,7 +237,7 @@
template <typename T,
typename CreateTrait = DefaultConstructTrait<T>,
- typename InitOnceTrait = SingleThreadInitOnceTrait,
+ typename InitOnceTrait = ThreadSafeInitOnceTrait,
typename DestroyTrait = LeakyInstanceTrait<T> >
struct LazyInstance {
// A LazyInstance is a LazyStaticInstance.
@@ -248,7 +248,7 @@
template <typename T,
typename CreateTrait = DefaultCreateTrait<T>,
- typename InitOnceTrait = SingleThreadInitOnceTrait,
+ typename InitOnceTrait = ThreadSafeInitOnceTrait,
typename DestroyTrait = LeakyInstanceTrait<T> >
struct LazyDynamicInstance {
typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>,
diff --git a/src/lithium-codegen.cc b/src/lithium-codegen.cc
index 3cd16db..0967af9 100644
--- a/src/lithium-codegen.cc
+++ b/src/lithium-codegen.cc
@@ -173,6 +173,18 @@
}
+static void AddWeakObjectToCodeDependency(Isolate* isolate,
+ Handle<Object> object,
+ Handle<Code> code) {
+ Heap* heap = isolate->heap();
+ heap->EnsureWeakObjectToCodeTable();
+ Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(*object));
+ dep = DependentCode::Insert(dep, DependentCode::kWeakCodeGroup, code);
+ CALL_HEAP_FUNCTION_VOID(isolate,
+ heap->AddWeakObjectToCodeDependency(*object, *dep));
+}
+
+
void LCodeGenBase::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
ASSERT(code->is_optimized_code());
ZoneList<Handle<Map> > maps(1, zone());
@@ -211,13 +223,13 @@
NoWeakObjectVerificationScope disable_verification_of_embedded_objects;
#endif
for (int i = 0; i < maps.length(); i++) {
- maps.at(i)->AddDependentCode(DependentCode::kWeakCodeGroup, code);
+ Map::AddDependentCode(maps.at(i), DependentCode::kWeakCodeGroup, code);
}
for (int i = 0; i < objects.length(); i++) {
- AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code);
+ AddWeakObjectToCodeDependency(isolate(), objects.at(i), code);
}
for (int i = 0; i < cells.length(); i++) {
- AddWeakObjectToCodeDependency(isolate()->heap(), cells.at(i), code);
+ AddWeakObjectToCodeDependency(isolate(), cells.at(i), code);
}
}
diff --git a/src/liveedit.cc b/src/liveedit.cc
index dbb06f2..d0eab5b 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -431,7 +431,7 @@
class LineEndsWrapper {
public:
explicit LineEndsWrapper(Handle<String> string)
- : ends_array_(CalculateLineEnds(string, false)),
+ : ends_array_(String::CalculateLineEnds(string, false)),
string_len_(string->length()) {
}
int length() {
@@ -852,7 +852,8 @@
Handle<Smi> start_pos(
Smi::FromInt(message_location.start_pos()), isolate);
Handle<Smi> end_pos(Smi::FromInt(message_location.end_pos()), isolate);
- Handle<JSValue> script_obj = GetScriptWrapper(message_location.script());
+ Handle<JSObject> script_obj =
+ Script::GetWrapper(message_location.script());
JSReceiver::SetProperty(
rethrow_exception, start_pos_key, start_pos, NONE, SLOPPY).Assert();
JSReceiver::SetProperty(
@@ -1887,8 +1888,8 @@
DropActivationsInActiveThread(shared_info_array, result, do_drop);
if (error_message != NULL) {
// Add error message as an array extra element.
- Handle<String> str = isolate->factory()->NewStringFromAscii(
- CStrVector(error_message));
+ Handle<String> str =
+ isolate->factory()->NewStringFromAsciiChecked(error_message);
SetElementSloppy(result, len, str);
}
return result;
diff --git a/src/log.cc b/src/log.cc
index 896350e..e326f18 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -1150,7 +1150,8 @@
// (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
Log::MessageBuilder msg(log_);
- Handle<Object> source = GetProperty(regexp, "source").ToHandleChecked();
+ Handle<Object> source = Object::GetProperty(
+ isolate_, regexp, "source").ToHandleChecked();
if (!source->IsString()) {
msg.Append("no source");
return;
@@ -1168,18 +1169,20 @@
msg.Append('/');
// global flag
- Handle<Object> global = GetProperty(regexp, "global").ToHandleChecked();
+ Handle<Object> global = Object::GetProperty(
+ isolate_, regexp, "global").ToHandleChecked();
if (global->IsTrue()) {
msg.Append('g');
}
// ignorecase flag
- Handle<Object> ignorecase =
- GetProperty(regexp, "ignoreCase").ToHandleChecked();
+ Handle<Object> ignorecase = Object::GetProperty(
+ isolate_, regexp, "ignoreCase").ToHandleChecked();
if (ignorecase->IsTrue()) {
msg.Append('i');
}
// multiline flag
- Handle<Object> multiline = GetProperty(regexp, "multiline").ToHandleChecked();
+ Handle<Object> multiline = Object::GetProperty(
+ isolate_, regexp, "multiline").ToHandleChecked();
if (multiline->IsTrue()) {
msg.Append('m');
}
@@ -1905,9 +1908,9 @@
Handle<String> func_name(shared->DebugName());
if (shared->script()->IsScript()) {
Handle<Script> script(Script::cast(shared->script()));
- int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
+ int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
int column_num =
- GetScriptColumnNumber(script, shared->start_position()) + 1;
+ Script::GetColumnNumber(script, shared->start_position()) + 1;
if (script->name()->IsString()) {
Handle<String> script_name(String::cast(script->name()));
if (line_num > 0) {
diff --git a/src/macros.py b/src/macros.py
index 0b69e6b..3eb906f 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -87,6 +87,10 @@
const kMinMonth = -10000000;
const kMaxMonth = 10000000;
+# Strict mode flags for passing to %SetProperty
+const kSloppyMode = 0;
+const kStrictMode = 1;
+
# Native cache ids.
const STRING_TO_REGEXP_CACHE_ID = 0;
@@ -97,7 +101,7 @@
# values of 'bar'.
macro IS_NULL(arg) = (arg === null);
macro IS_NULL_OR_UNDEFINED(arg) = (arg == null);
-macro IS_UNDEFINED(arg) = (typeof(arg) === 'undefined');
+macro IS_UNDEFINED(arg) = (arg === (void 0));
macro IS_NUMBER(arg) = (typeof(arg) === 'number');
macro IS_STRING(arg) = (typeof(arg) === 'string');
macro IS_BOOLEAN(arg) = (typeof(arg) === 'boolean');
@@ -272,3 +276,8 @@
const PROPERTY_ATTRIBUTES_STRING = 8;
const PROPERTY_ATTRIBUTES_SYMBOLIC = 16;
const PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL = 32;
+
+# Use for keys, values and entries iterators.
+const ITERATOR_KIND_KEYS = 1;
+const ITERATOR_KIND_VALUES = 2;
+const ITERATOR_KIND_ENTRIES = 3;
diff --git a/src/messages.cc b/src/messages.cc
index 3445d4d..ad4bc8d 100644
--- a/src/messages.cc
+++ b/src/messages.cc
@@ -78,7 +78,7 @@
if (loc) {
start = loc->start_pos();
end = loc->end_pos();
- script_handle = GetScriptWrapper(loc->script());
+ script_handle = Script::GetWrapper(loc->script());
}
Handle<Object> stack_frames_handle = stack_frames.is_null()
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
index b659559..f3a57f9 100644
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -46,6 +46,7 @@
#ifdef DEBUG
bool CpuFeatures::initialized_ = false;
#endif
+bool CpuFeatures::hint_creating_snapshot_ = false;
unsigned CpuFeatures::supported_ = 0;
unsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
unsigned CpuFeatures::cross_compile_ = 0;
@@ -102,10 +103,27 @@
}
+void CpuFeatures::SetHintCreatingSnapshot() {
+ hint_creating_snapshot_ = true;
+}
+
+
+void CpuFeatures::ProbeWithoutIsolate() {
+ Probe(hint_creating_snapshot_);
+}
+
+
void CpuFeatures::Probe() {
+ // The Serializer can only be queried after isolate initialization.
+ Probe(Serializer::enabled());
+}
+
+
+void CpuFeatures::Probe(bool serializer_enabled) {
unsigned standard_features = (OS::CpuFeaturesImpliedByPlatform() |
CpuFeaturesImpliedByCompiler());
- ASSERT(supported_ == 0 || supported_ == standard_features);
+ ASSERT(supported_ == 0 ||
+ (supported_ & standard_features) == standard_features);
#ifdef DEBUG
initialized_ = true;
#endif
@@ -115,7 +133,7 @@
// snapshot.
supported_ |= standard_features;
- if (Serializer::enabled()) {
+ if (serializer_enabled) {
// No probing for features if we might serialize (generate snapshot).
return;
}
@@ -1655,10 +1673,12 @@
void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
// Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
// load to two 32-bit loads.
- GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
+ GenInstrImmediate(LWC1, src.rm(), fd, src.offset_ +
+ Register::kMantissaOffset);
FPURegister nextfpreg;
nextfpreg.setcode(fd.code() + 1);
- GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ + 4);
+ GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ +
+ Register::kExponentOffset);
}
@@ -1670,10 +1690,12 @@
void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
// Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
// store to two 32-bit stores.
- GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
+ GenInstrImmediate(SWC1, src.rm(), fd, src.offset_ +
+ Register::kMantissaOffset);
FPURegister nextfpreg;
nextfpreg.setcode(fd.code() + 1);
- GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ + 4);
+ GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ +
+ Register::kExponentOffset);
}
@@ -2075,11 +2097,6 @@
if (!RelocInfo::IsNone(rinfo.rmode())) {
// Don't record external references unless the heap will be serialized.
if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
-#ifdef DEBUG
- if (!Serializer::enabled()) {
- Serializer::TooLateToEnableNow();
- }
-#endif
if (!Serializer::enabled() && !emit_debug_code()) {
return;
}
@@ -2328,16 +2345,17 @@
}
-MaybeObject* Assembler::AllocateConstantPool(Heap* heap) {
+Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
// No out-of-line constant pool support.
- UNREACHABLE();
- return NULL;
+ ASSERT(!FLAG_enable_ool_constant_pool);
+ return isolate->factory()->empty_constant_pool_array();
}
void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
// No out-of-line constant pool support.
- UNREACHABLE();
+ ASSERT(!FLAG_enable_ool_constant_pool);
+ return;
}
diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h
index ea956e1..e4729b2 100644
--- a/src/mips/assembler-mips.h
+++ b/src/mips/assembler-mips.h
@@ -77,6 +77,16 @@
static const int kSizeInBytes = 4;
static const int kCpRegister = 23; // cp (s7) is the 23rd register.
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+ static const int kMantissaOffset = 0;
+ static const int kExponentOffset = 4;
+#elif defined(V8_TARGET_BIG_ENDIAN)
+ static const int kMantissaOffset = 4;
+ static const int kExponentOffset = 0;
+#else
+#error Unknown endianness
+#endif
+
inline static int NumAllocatableRegisters();
static int ToAllocationIndex(Register reg) {
@@ -417,6 +427,11 @@
// is enabled (snapshots must be portable).
static void Probe();
+ // A special case for printing target and features, which we want to do
+ // before initializing the isolate
+ static void SetHintCreatingSnapshot();
+ static void ProbeWithoutIsolate();
+
// Check whether a feature is supported by the target CPU.
static bool IsSupported(CpuFeature f) {
ASSERT(initialized_);
@@ -445,6 +460,9 @@
}
private:
+ static void Probe(bool serializer_enabled);
+ static bool hint_creating_snapshot_;
+
static bool Check(CpuFeature f, unsigned set) {
return (set & flag2set(f)) != 0;
}
@@ -1007,7 +1025,7 @@
void CheckTrampolinePool();
// Allocate a constant pool of the correct size for the generated code.
- MaybeObject* AllocateConstantPool(Heap* heap);
+ Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
// Generate the constant pool for the generated code.
void PopulateConstantPool(ConstantPoolArray* constant_pool);
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 03d6cc8..38ed464 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -470,9 +470,7 @@
if (count_constructions) {
__ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
- __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
- __ Ext(a0, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
- kBitsPerByte);
+ __ lbu(a0, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset));
__ sll(at, a0, kPointerSizeLog2);
__ addu(a0, t5, at);
__ sll(at, a3, kPointerSizeLog2);
@@ -525,12 +523,9 @@
__ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
// The field instance sizes contains both pre-allocated property fields
// and in-object properties.
- __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
- __ Ext(t6, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
- kBitsPerByte);
+ __ lbu(t6, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset));
__ Addu(a3, a3, Operand(t6));
- __ Ext(t6, a0, Map::kInObjectPropertiesByte * kBitsPerByte,
- kBitsPerByte);
+ __ lbu(t6, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
__ subu(a3, a3, t6);
// Done if no extra properties are to be allocated.
@@ -1305,7 +1300,7 @@
// Out of stack space.
__ lw(a1, MemOperand(fp, kFunctionOffset));
__ Push(a1, v0);
- __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
// End of stack check.
// Push current limit and index.
@@ -1426,6 +1421,27 @@
}
+static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
+ Label* stack_overflow) {
+ // ----------- S t a t e -------------
+ // -- a0 : actual number of arguments
+ // -- a1 : function (passed through to callee)
+ // -- a2 : expected number of arguments
+ // -----------------------------------
+ // Check the stack for overflow. We are not trying to catch
+ // interruptions (e.g. debug break and preemption) here, so the "real stack
+ // limit" is checked.
+ __ LoadRoot(t1, Heap::kRealStackLimitRootIndex);
+ // Make t1 the space we have left. The stack might already be overflowed
+ // here which will cause t1 to become negative.
+ __ subu(t1, sp, t1);
+ // Check if the arguments will overflow the stack.
+ __ sll(at, a2, kPointerSizeLog2);
+ // Signed comparison.
+ __ Branch(stack_overflow, le, t1, Operand(at));
+}
+
+
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
__ sll(a0, a0, kSmiTagSize);
__ li(t0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
@@ -1460,6 +1476,8 @@
// -- a2: expected arguments count
// -----------------------------------
+ Label stack_overflow;
+ ArgumentAdaptorStackCheck(masm, &stack_overflow);
Label invoke, dont_adapt_arguments;
Label enough, too_few;
@@ -1568,6 +1586,14 @@
// -------------------------------------------
__ bind(&dont_adapt_arguments);
__ Jump(a3);
+
+ __ bind(&stack_overflow);
+ {
+ FrameScope frame(masm, StackFrame::MANUAL);
+ EnterArgumentsAdaptorFrame(masm);
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
+ __ break_(0xCC);
+ }
}
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 7851b58..1d94e70 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -559,13 +559,14 @@
void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
-#ifndef BIG_ENDIAN_FLOATING_POINT
- Register exponent = result1_;
- Register mantissa = result2_;
-#else
- Register exponent = result2_;
- Register mantissa = result1_;
-#endif
+ Register exponent, mantissa;
+ if (kArchEndian == kLittle) {
+ exponent = result1_;
+ mantissa = result2_;
+ } else {
+ exponent = result2_;
+ mantissa = result1_;
+ }
Label not_special;
// Convert from Smi to integer.
__ sra(source_, source_, kSmiTagSize);
@@ -671,8 +672,10 @@
Register input_high = scratch2;
Register input_low = scratch3;
- __ lw(input_low, MemOperand(input_reg, double_offset));
- __ lw(input_high, MemOperand(input_reg, double_offset + kIntSize));
+ __ lw(input_low,
+ MemOperand(input_reg, double_offset + Register::kMantissaOffset));
+ __ lw(input_high,
+ MemOperand(input_reg, double_offset + Register::kExponentOffset));
Label normal_exponent, restore_sign;
// Extract the biased exponent in result.
@@ -1607,35 +1610,35 @@
}
-void CEntryStub::GenerateCore(MacroAssembler* masm,
- Label* throw_normal_exception,
- Label* throw_termination_exception,
- bool do_gc,
- bool always_allocate) {
- // v0: result parameter for PerformGC, if any
- // s0: number of arguments including receiver (C callee-saved)
- // s1: pointer to the first argument (C callee-saved)
- // s2: pointer to builtin function (C callee-saved)
+void CEntryStub::Generate(MacroAssembler* masm) {
+ // Called from JavaScript; parameters are on stack as if calling JS function
+ // s0: number of arguments including receiver
+ // s1: size of arguments excluding receiver
+ // s2: pointer to builtin function
+ // fp: frame pointer (restored after C call)
+ // sp: stack pointer (restored as callee's sp after C call)
+ // cp: current context (C callee-saved)
+
+ ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
+ // NOTE: s0-s2 hold the arguments of this function instead of a0-a2.
+ // The reason for this is that these arguments would need to be saved anyway
+ // so it's faster to set them up directly.
+ // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction.
+
+ // Compute the argv pointer in a callee-saved register.
+ __ Addu(s1, sp, s1);
+
+ // Enter the exit frame that transitions from JavaScript to C++.
+ FrameScope scope(masm, StackFrame::MANUAL);
+ __ EnterExitFrame(save_doubles_);
+
+ // s0: number of arguments including receiver (C callee-saved)
+ // s1: pointer to first argument (C callee-saved)
+ // s2: pointer to builtin function (C callee-saved)
Isolate* isolate = masm->isolate();
- if (do_gc) {
- // Move result passed in v0 into a0 to call PerformGC.
- __ mov(a0, v0);
- __ PrepareCallCFunction(2, 0, a1);
- __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
- __ CallCFunction(ExternalReference::perform_gc_function(isolate), 2, 0);
- }
-
- ExternalReference scope_depth =
- ExternalReference::heap_always_allocate_scope_depth(isolate);
- if (always_allocate) {
- __ li(a0, Operand(scope_depth));
- __ lw(a1, MemOperand(a0));
- __ Addu(a1, a1, Operand(1));
- __ sw(a1, MemOperand(a0));
- }
-
// Prepare arguments for C routine.
// a0 = argc
__ mov(a0, s0);
@@ -1681,130 +1684,67 @@
masm->InstructionsGeneratedSince(&find_ra));
}
- if (always_allocate) {
- // It's okay to clobber a2 and a3 here. v0 & v1 contain result.
- __ li(a2, Operand(scope_depth));
- __ lw(a3, MemOperand(a2));
- __ Subu(a3, a3, Operand(1));
- __ sw(a3, MemOperand(a2));
+
+ // Runtime functions should not return 'the hole'. Allowing it to escape may
+ // lead to crashes in the IC code later.
+ if (FLAG_debug_code) {
+ Label okay;
+ __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
+ __ Branch(&okay, ne, v0, Operand(t0));
+ __ stop("The hole escaped");
+ __ bind(&okay);
}
- // Check for failure result.
- Label failure_returned;
- STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
- __ addiu(a2, v0, 1);
- __ andi(t0, a2, kFailureTagMask);
- __ Branch(USE_DELAY_SLOT, &failure_returned, eq, t0, Operand(zero_reg));
- // Restore stack (remove arg slots) in branch delay slot.
- __ addiu(sp, sp, kCArgsSlotsSize);
+ // Check result for exception sentinel.
+ Label exception_returned;
+ __ LoadRoot(t0, Heap::kExceptionRootIndex);
+ __ Branch(&exception_returned, eq, t0, Operand(v0));
+ ExternalReference pending_exception_address(
+ Isolate::kPendingExceptionAddress, isolate);
+
+ // Check that there is no pending exception, otherwise we
+ // should have returned the exception sentinel.
+ if (FLAG_debug_code) {
+ Label okay;
+ __ li(a2, Operand(pending_exception_address));
+ __ lw(a2, MemOperand(a2));
+ __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
+ // Cannot use check here as it attempts to generate call into runtime.
+ __ Branch(&okay, eq, t0, Operand(a2));
+ __ stop("Unexpected pending exception");
+ __ bind(&okay);
+ }
// Exit C frame and return.
// v0:v1: result
// sp: stack pointer
// fp: frame pointer
+ // s0: still holds argc (callee-saved).
__ LeaveExitFrame(save_doubles_, s0, true, EMIT_RETURN);
- // Check if we should retry or throw exception.
- Label retry;
- __ bind(&failure_returned);
- STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
- __ andi(t0, v0, ((1 << kFailureTypeTagSize) - 1) << kFailureTagSize);
- __ Branch(&retry, eq, t0, Operand(zero_reg));
+ // Handling of exception.
+ __ bind(&exception_returned);
// Retrieve the pending exception.
- __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
- isolate)));
- __ lw(v0, MemOperand(t0));
+ __ li(a2, Operand(pending_exception_address));
+ __ lw(v0, MemOperand(a2));
// Clear the pending exception.
__ li(a3, Operand(isolate->factory()->the_hole_value()));
- __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
- isolate)));
- __ sw(a3, MemOperand(t0));
+ __ sw(a3, MemOperand(a2));
// Special handling of termination exceptions which are uncatchable
// by javascript code.
+ Label throw_termination_exception;
__ LoadRoot(t0, Heap::kTerminationExceptionRootIndex);
- __ Branch(throw_termination_exception, eq, v0, Operand(t0));
+ __ Branch(&throw_termination_exception, eq, v0, Operand(t0));
// Handle normal exception.
- __ jmp(throw_normal_exception);
-
- __ bind(&retry);
- // Last failure (v0) will be moved to (a0) for parameter when retrying.
-}
-
-
-void CEntryStub::Generate(MacroAssembler* masm) {
- // Called from JavaScript; parameters are on stack as if calling JS function
- // s0: number of arguments including receiver
- // s1: size of arguments excluding receiver
- // s2: pointer to builtin function
- // fp: frame pointer (restored after C call)
- // sp: stack pointer (restored as callee's sp after C call)
- // cp: current context (C callee-saved)
-
- ProfileEntryHookStub::MaybeCallEntryHook(masm);
-
- // NOTE: Invocations of builtins may return failure objects
- // instead of a proper result. The builtin entry handles
- // this by performing a garbage collection and retrying the
- // builtin once.
-
- // NOTE: s0-s2 hold the arguments of this function instead of a0-a2.
- // The reason for this is that these arguments would need to be saved anyway
- // so it's faster to set them up directly.
- // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction.
-
- // Compute the argv pointer in a callee-saved register.
- __ Addu(s1, sp, s1);
-
- // Enter the exit frame that transitions from JavaScript to C++.
- FrameScope scope(masm, StackFrame::MANUAL);
- __ EnterExitFrame(save_doubles_);
-
- // s0: number of arguments (C callee-saved)
- // s1: pointer to first argument (C callee-saved)
- // s2: pointer to builtin function (C callee-saved)
-
- Label throw_normal_exception;
- Label throw_termination_exception;
-
- // Call into the runtime system.
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- false,
- false);
-
- // Do space-specific GC and retry runtime call.
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- true,
- false);
-
- // Do full GC and retry runtime call one final time.
- Failure* failure = Failure::InternalError();
- __ li(v0, Operand(reinterpret_cast<int32_t>(failure)));
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- true,
- true);
-
- { FrameScope scope(masm, StackFrame::MANUAL);
- __ PrepareCallCFunction(0, v0);
- __ CallCFunction(
- ExternalReference::out_of_memory_function(masm->isolate()), 0);
- }
+ __ Throw(v0);
__ bind(&throw_termination_exception);
__ ThrowUncatchable(v0);
-
- __ bind(&throw_normal_exception);
- __ Throw(v0);
}
@@ -1896,7 +1836,7 @@
__ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
isolate)));
__ sw(v0, MemOperand(t0)); // We come back from 'invoke'. result is in v0.
- __ li(v0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
+ __ LoadRoot(v0, Heap::kExceptionRootIndex);
__ b(&exit); // b exposes branch delay slot.
__ nop(); // Branch delay slot nop.
@@ -3532,9 +3472,15 @@
{
Label loop;
__ bind(&loop);
- __ lwr(scratch1, MemOperand(src));
- __ Addu(src, src, Operand(kReadAlignment));
- __ lwl(scratch1, MemOperand(src, -1));
+ if (kArchEndian == kBig) {
+ __ lwl(scratch1, MemOperand(src));
+ __ Addu(src, src, Operand(kReadAlignment));
+ __ lwr(scratch1, MemOperand(src, -1));
+ } else {
+ __ lwr(scratch1, MemOperand(src));
+ __ Addu(src, src, Operand(kReadAlignment));
+ __ lwl(scratch1, MemOperand(src, -1));
+ }
__ sw(scratch1, MemOperand(dest));
__ Addu(dest, dest, Operand(kReadAlignment));
__ Subu(scratch2, limit, dest);
@@ -3999,206 +3945,6 @@
}
-void ArrayPushStub::Generate(MacroAssembler* masm) {
- Register receiver = a0;
- Register scratch = a1;
-
- int argc = arguments_count();
-
- if (argc == 0) {
- // Nothing to do, just return the length.
- __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ DropAndRet(argc + 1);
- return;
- }
-
- Isolate* isolate = masm->isolate();
-
- if (argc != 1) {
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- Label call_builtin, attempt_to_grow_elements, with_write_barrier;
-
- Register elements = t2;
- Register end_elements = t1;
- // Get the elements array of the object.
- __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
-
- if (IsFastSmiOrObjectElementsKind(elements_kind())) {
- // Check that the elements are in fast mode and writable.
- __ CheckMap(elements,
- scratch,
- Heap::kFixedArrayMapRootIndex,
- &call_builtin,
- DONT_DO_SMI_CHECK);
- }
-
- // Get the array's length into scratch and calculate new length.
- __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ Addu(scratch, scratch, Operand(Smi::FromInt(argc)));
-
- // Get the elements' length.
- __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
-
- const int kEndElementsOffset =
- FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
-
- if (IsFastSmiOrObjectElementsKind(elements_kind())) {
- // Check if we could survive without allocation.
- __ Branch(&attempt_to_grow_elements, gt, scratch, Operand(t0));
-
- // Check if value is a smi.
- __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize));
- __ JumpIfNotSmi(t0, &with_write_barrier);
-
- // Store the value.
- // We may need a register containing the address end_elements below,
- // so write back the value in end_elements.
- __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize);
- __ Addu(end_elements, elements, end_elements);
- __ Addu(end_elements, end_elements, kEndElementsOffset);
- __ sw(t0, MemOperand(end_elements));
- } else {
- // Check if we could survive without allocation.
- __ Branch(&call_builtin, gt, scratch, Operand(t0));
-
- __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize));
- __ StoreNumberToDoubleElements(t0, scratch, elements, a3, t1, a2,
- &call_builtin, argc * kDoubleSize);
- }
-
- // Save new length.
- __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ mov(v0, scratch);
- __ DropAndRet(argc + 1);
-
- if (IsFastDoubleElementsKind(elements_kind())) {
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- __ bind(&with_write_barrier);
-
- if (IsFastSmiElementsKind(elements_kind())) {
- if (FLAG_trace_elements_transitions) __ jmp(&call_builtin);
-
- __ lw(t3, FieldMemOperand(t0, HeapObject::kMapOffset));
- __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
- __ Branch(&call_builtin, eq, t3, Operand(at));
-
- ElementsKind target_kind = IsHoleyElementsKind(elements_kind())
- ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
- __ lw(a3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
- __ lw(a3, FieldMemOperand(a3, GlobalObject::kNativeContextOffset));
- __ lw(a3, ContextOperand(a3, Context::JS_ARRAY_MAPS_INDEX));
- const int header_size = FixedArrayBase::kHeaderSize;
- // Verify that the object can be transitioned in place.
- const int origin_offset = header_size + elements_kind() * kPointerSize;
- __ lw(a2, FieldMemOperand(receiver, origin_offset));
- __ lw(at, FieldMemOperand(a3, HeapObject::kMapOffset));
- __ Branch(&call_builtin, ne, a2, Operand(at));
-
-
- const int target_offset = header_size + target_kind * kPointerSize;
- __ lw(a3, FieldMemOperand(a3, target_offset));
- __ mov(a2, receiver);
- ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
- masm, DONT_TRACK_ALLOCATION_SITE, NULL);
- }
-
- // Save new length.
- __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
-
- // Store the value.
- // We may need a register containing the address end_elements below, so write
- // back the value in end_elements.
- __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize);
- __ Addu(end_elements, elements, end_elements);
- __ Addu(end_elements, end_elements, kEndElementsOffset);
- __ sw(t0, MemOperand(end_elements));
-
- __ RecordWrite(elements,
- end_elements,
- t0,
- kRAHasNotBeenSaved,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- __ mov(v0, scratch);
- __ DropAndRet(argc + 1);
-
- __ bind(&attempt_to_grow_elements);
- // scratch: array's length + 1.
-
- if (!FLAG_inline_new) {
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize));
- // Growing elements that are SMI-only requires special handling in case the
- // new element is non-Smi. For now, delegate to the builtin.
- if (IsFastSmiElementsKind(elements_kind())) {
- __ JumpIfNotSmi(a2, &call_builtin);
- }
-
- // We could be lucky and the elements array could be at the top of new-space.
- // In this case we can just grow it in place by moving the allocation pointer
- // up.
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate);
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate);
-
- const int kAllocationDelta = 4;
- ASSERT(kAllocationDelta >= argc);
- // Load top and check if it is the end of elements.
- __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize);
- __ Addu(end_elements, elements, end_elements);
- __ Addu(end_elements, end_elements, Operand(kEndElementsOffset));
- __ li(t0, Operand(new_space_allocation_top));
- __ lw(a3, MemOperand(t0));
- __ Branch(&call_builtin, ne, a3, Operand(end_elements));
-
- __ li(t3, Operand(new_space_allocation_limit));
- __ lw(t3, MemOperand(t3));
- __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize));
- __ Branch(&call_builtin, hi, a3, Operand(t3));
-
- // We fit and could grow elements.
- // Update new_space_allocation_top.
- __ sw(a3, MemOperand(t0));
- // Push the argument.
- __ sw(a2, MemOperand(end_elements));
- // Fill the rest with holes.
- __ LoadRoot(a3, Heap::kTheHoleValueRootIndex);
- for (int i = 1; i < kAllocationDelta; i++) {
- __ sw(a3, MemOperand(end_elements, i * kPointerSize));
- }
-
- // Update elements' and array's sizes.
- __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
- __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta)));
- __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
-
- // Elements are in new space, so write barrier is not required.
- __ mov(v0, scratch);
- __ DropAndRet(argc + 1);
-
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
-}
-
-
void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a1 : left
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index 1b79433..a2b976d 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -67,21 +67,13 @@
Register temp2 = t1;
Register temp3 = t2;
- if (!IsMipsSoftFloatABI) {
- // Input value is in f12 anyway, nothing to do.
- } else {
- __ Move(input, a0, a1);
- }
+ __ MovFromFloatParameter(input);
__ Push(temp3, temp2, temp1);
MathExpGenerator::EmitMathExp(
&masm, input, result, double_scratch1, double_scratch2,
temp1, temp2, temp3);
__ Pop(temp3, temp2, temp1);
- if (!IsMipsSoftFloatABI) {
- // Result is already in f0, nothing to do.
- } else {
- __ Move(v0, v1, result);
- }
+ __ MovToFloatResult(result);
__ Ret();
}
@@ -167,11 +159,17 @@
__ beq(a3, zero_reg, &aligned); // Already aligned.
__ subu(a2, a2, a3); // In delay slot. a2 is the remining bytes count.
- __ lwr(t8, MemOperand(a1));
- __ addu(a1, a1, a3);
- __ swr(t8, MemOperand(a0));
- __ addu(a0, a0, a3);
-
+ if (kArchEndian == kLittle) {
+ __ lwr(t8, MemOperand(a1));
+ __ addu(a1, a1, a3);
+ __ swr(t8, MemOperand(a0));
+ __ addu(a0, a0, a3);
+ } else {
+ __ lwl(t8, MemOperand(a1));
+ __ addu(a1, a1, a3);
+ __ swl(t8, MemOperand(a0));
+ __ addu(a0, a0, a3);
+ }
// Now dst/src are both aligned to (word) aligned addresses. Set a2 to
// count how many bytes we have to copy after all the 64 byte chunks are
// copied and a3 to the dst pointer after all the 64 byte chunks have been
@@ -323,12 +321,21 @@
__ beq(a3, zero_reg, &ua_chk16w);
__ subu(a2, a2, a3); // In delay slot.
- __ lwr(v1, MemOperand(a1));
- __ lwl(v1,
- MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
- __ addu(a1, a1, a3);
- __ swr(v1, MemOperand(a0));
- __ addu(a0, a0, a3);
+ if (kArchEndian == kLittle) {
+ __ lwr(v1, MemOperand(a1));
+ __ lwl(v1,
+ MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
+ __ addu(a1, a1, a3);
+ __ swr(v1, MemOperand(a0));
+ __ addu(a0, a0, a3);
+ } else {
+ __ lwl(v1, MemOperand(a1));
+ __ lwr(v1,
+ MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
+ __ addu(a1, a1, a3);
+ __ swl(v1, MemOperand(a0));
+ __ addu(a0, a0, a3);
+ }
// Now the dst (but not the source) is aligned. Set a2 to count how many
// bytes we have to copy after all the 64 byte chunks are copied and a3 to
@@ -357,40 +364,77 @@
__ bind(&ua_loop16w);
__ Pref(pref_hint_load, MemOperand(a1, 3 * pref_chunk));
- __ lwr(t0, MemOperand(a1));
- __ lwr(t1, MemOperand(a1, 1, loadstore_chunk));
- __ lwr(t2, MemOperand(a1, 2, loadstore_chunk));
+ if (kArchEndian == kLittle) {
+ __ lwr(t0, MemOperand(a1));
+ __ lwr(t1, MemOperand(a1, 1, loadstore_chunk));
+ __ lwr(t2, MemOperand(a1, 2, loadstore_chunk));
- if (pref_hint_store == kPrefHintPrepareForStore) {
- __ sltu(v1, t9, a0);
- __ Branch(USE_DELAY_SLOT, &ua_skip_pref, gt, v1, Operand(zero_reg));
+ if (pref_hint_store == kPrefHintPrepareForStore) {
+ __ sltu(v1, t9, a0);
+ __ Branch(USE_DELAY_SLOT, &ua_skip_pref, gt, v1, Operand(zero_reg));
+ }
+ __ lwr(t3, MemOperand(a1, 3, loadstore_chunk)); // Maybe in delay slot.
+
+ __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk));
+ __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk));
+
+ __ bind(&ua_skip_pref);
+ __ lwr(t4, MemOperand(a1, 4, loadstore_chunk));
+ __ lwr(t5, MemOperand(a1, 5, loadstore_chunk));
+ __ lwr(t6, MemOperand(a1, 6, loadstore_chunk));
+ __ lwr(t7, MemOperand(a1, 7, loadstore_chunk));
+ __ lwl(t0,
+ MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t1,
+ MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t2,
+ MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t3,
+ MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t4,
+ MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t5,
+ MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t6,
+ MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t7,
+ MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
+ } else {
+ __ lwl(t0, MemOperand(a1));
+ __ lwl(t1, MemOperand(a1, 1, loadstore_chunk));
+ __ lwl(t2, MemOperand(a1, 2, loadstore_chunk));
+
+ if (pref_hint_store == kPrefHintPrepareForStore) {
+ __ sltu(v1, t9, a0);
+ __ Branch(USE_DELAY_SLOT, &ua_skip_pref, gt, v1, Operand(zero_reg));
+ }
+ __ lwl(t3, MemOperand(a1, 3, loadstore_chunk)); // Maybe in delay slot.
+
+ __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk));
+ __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk));
+
+ __ bind(&ua_skip_pref);
+ __ lwl(t4, MemOperand(a1, 4, loadstore_chunk));
+ __ lwl(t5, MemOperand(a1, 5, loadstore_chunk));
+ __ lwl(t6, MemOperand(a1, 6, loadstore_chunk));
+ __ lwl(t7, MemOperand(a1, 7, loadstore_chunk));
+ __ lwr(t0,
+ MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t1,
+ MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t2,
+ MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t3,
+ MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t4,
+ MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t5,
+ MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t6,
+ MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t7,
+ MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
}
- __ lwr(t3, MemOperand(a1, 3, loadstore_chunk)); // Maybe in delay slot.
-
- __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk));
- __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk));
-
- __ bind(&ua_skip_pref);
- __ lwr(t4, MemOperand(a1, 4, loadstore_chunk));
- __ lwr(t5, MemOperand(a1, 5, loadstore_chunk));
- __ lwr(t6, MemOperand(a1, 6, loadstore_chunk));
- __ lwr(t7, MemOperand(a1, 7, loadstore_chunk));
- __ lwl(t0,
- MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t1,
- MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t2,
- MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t3,
- MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t4,
- MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t5,
- MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t6,
- MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t7,
- MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
__ Pref(pref_hint_load, MemOperand(a1, 4 * pref_chunk));
__ sw(t0, MemOperand(a0));
__ sw(t1, MemOperand(a0, 1, loadstore_chunk));
@@ -400,30 +444,57 @@
__ sw(t5, MemOperand(a0, 5, loadstore_chunk));
__ sw(t6, MemOperand(a0, 6, loadstore_chunk));
__ sw(t7, MemOperand(a0, 7, loadstore_chunk));
- __ lwr(t0, MemOperand(a1, 8, loadstore_chunk));
- __ lwr(t1, MemOperand(a1, 9, loadstore_chunk));
- __ lwr(t2, MemOperand(a1, 10, loadstore_chunk));
- __ lwr(t3, MemOperand(a1, 11, loadstore_chunk));
- __ lwr(t4, MemOperand(a1, 12, loadstore_chunk));
- __ lwr(t5, MemOperand(a1, 13, loadstore_chunk));
- __ lwr(t6, MemOperand(a1, 14, loadstore_chunk));
- __ lwr(t7, MemOperand(a1, 15, loadstore_chunk));
- __ lwl(t0,
- MemOperand(a1, 9, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t1,
- MemOperand(a1, 10, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t2,
- MemOperand(a1, 11, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t3,
- MemOperand(a1, 12, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t4,
- MemOperand(a1, 13, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t5,
- MemOperand(a1, 14, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t6,
- MemOperand(a1, 15, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t7,
- MemOperand(a1, 16, loadstore_chunk, MemOperand::offset_minus_one));
+ if (kArchEndian == kLittle) {
+ __ lwr(t0, MemOperand(a1, 8, loadstore_chunk));
+ __ lwr(t1, MemOperand(a1, 9, loadstore_chunk));
+ __ lwr(t2, MemOperand(a1, 10, loadstore_chunk));
+ __ lwr(t3, MemOperand(a1, 11, loadstore_chunk));
+ __ lwr(t4, MemOperand(a1, 12, loadstore_chunk));
+ __ lwr(t5, MemOperand(a1, 13, loadstore_chunk));
+ __ lwr(t6, MemOperand(a1, 14, loadstore_chunk));
+ __ lwr(t7, MemOperand(a1, 15, loadstore_chunk));
+ __ lwl(t0,
+ MemOperand(a1, 9, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t1,
+ MemOperand(a1, 10, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t2,
+ MemOperand(a1, 11, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t3,
+ MemOperand(a1, 12, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t4,
+ MemOperand(a1, 13, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t5,
+ MemOperand(a1, 14, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t6,
+ MemOperand(a1, 15, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t7,
+ MemOperand(a1, 16, loadstore_chunk, MemOperand::offset_minus_one));
+ } else {
+ __ lwl(t0, MemOperand(a1, 8, loadstore_chunk));
+ __ lwl(t1, MemOperand(a1, 9, loadstore_chunk));
+ __ lwl(t2, MemOperand(a1, 10, loadstore_chunk));
+ __ lwl(t3, MemOperand(a1, 11, loadstore_chunk));
+ __ lwl(t4, MemOperand(a1, 12, loadstore_chunk));
+ __ lwl(t5, MemOperand(a1, 13, loadstore_chunk));
+ __ lwl(t6, MemOperand(a1, 14, loadstore_chunk));
+ __ lwl(t7, MemOperand(a1, 15, loadstore_chunk));
+ __ lwr(t0,
+ MemOperand(a1, 9, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t1,
+ MemOperand(a1, 10, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t2,
+ MemOperand(a1, 11, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t3,
+ MemOperand(a1, 12, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t4,
+ MemOperand(a1, 13, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t5,
+ MemOperand(a1, 14, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t6,
+ MemOperand(a1, 15, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t7,
+ MemOperand(a1, 16, loadstore_chunk, MemOperand::offset_minus_one));
+ }
__ Pref(pref_hint_load, MemOperand(a1, 5 * pref_chunk));
__ sw(t0, MemOperand(a0, 8, loadstore_chunk));
__ sw(t1, MemOperand(a0, 9, loadstore_chunk));
@@ -447,30 +518,57 @@
__ beq(a2, t8, &ua_chk1w);
__ nop(); // In delay slot.
- __ lwr(t0, MemOperand(a1));
- __ lwr(t1, MemOperand(a1, 1, loadstore_chunk));
- __ lwr(t2, MemOperand(a1, 2, loadstore_chunk));
- __ lwr(t3, MemOperand(a1, 3, loadstore_chunk));
- __ lwr(t4, MemOperand(a1, 4, loadstore_chunk));
- __ lwr(t5, MemOperand(a1, 5, loadstore_chunk));
- __ lwr(t6, MemOperand(a1, 6, loadstore_chunk));
- __ lwr(t7, MemOperand(a1, 7, loadstore_chunk));
- __ lwl(t0,
- MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t1,
- MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t2,
- MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t3,
- MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t4,
- MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t5,
- MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t6,
- MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
- __ lwl(t7,
- MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
+ if (kArchEndian == kLittle) {
+ __ lwr(t0, MemOperand(a1));
+ __ lwr(t1, MemOperand(a1, 1, loadstore_chunk));
+ __ lwr(t2, MemOperand(a1, 2, loadstore_chunk));
+ __ lwr(t3, MemOperand(a1, 3, loadstore_chunk));
+ __ lwr(t4, MemOperand(a1, 4, loadstore_chunk));
+ __ lwr(t5, MemOperand(a1, 5, loadstore_chunk));
+ __ lwr(t6, MemOperand(a1, 6, loadstore_chunk));
+ __ lwr(t7, MemOperand(a1, 7, loadstore_chunk));
+ __ lwl(t0,
+ MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t1,
+ MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t2,
+ MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t3,
+ MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t4,
+ MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t5,
+ MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t6,
+ MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwl(t7,
+ MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
+ } else {
+ __ lwl(t0, MemOperand(a1));
+ __ lwl(t1, MemOperand(a1, 1, loadstore_chunk));
+ __ lwl(t2, MemOperand(a1, 2, loadstore_chunk));
+ __ lwl(t3, MemOperand(a1, 3, loadstore_chunk));
+ __ lwl(t4, MemOperand(a1, 4, loadstore_chunk));
+ __ lwl(t5, MemOperand(a1, 5, loadstore_chunk));
+ __ lwl(t6, MemOperand(a1, 6, loadstore_chunk));
+ __ lwl(t7, MemOperand(a1, 7, loadstore_chunk));
+ __ lwr(t0,
+ MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t1,
+ MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t2,
+ MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t3,
+ MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t4,
+ MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t5,
+ MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t6,
+ MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
+ __ lwr(t7,
+ MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
+ }
__ addiu(a1, a1, 8 * loadstore_chunk);
__ sw(t0, MemOperand(a0));
__ sw(t1, MemOperand(a0, 1, loadstore_chunk));
@@ -491,9 +589,15 @@
__ addu(a3, a0, a3);
__ bind(&ua_wordCopy_loop);
- __ lwr(v1, MemOperand(a1));
- __ lwl(v1,
- MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
+ if (kArchEndian == kLittle) {
+ __ lwr(v1, MemOperand(a1));
+ __ lwl(v1,
+ MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
+ } else {
+ __ lwl(v1, MemOperand(a1));
+ __ lwr(v1,
+ MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
+ }
__ addiu(a0, a0, loadstore_chunk);
__ addiu(a1, a1, loadstore_chunk);
__ bne(a0, a3, &ua_wordCopy_loop);
@@ -722,8 +826,8 @@
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Assert(eq, kObjectFoundInSmiOnlyArray, at, Operand(t5));
}
- __ sw(t0, MemOperand(t3)); // mantissa
- __ sw(t1, MemOperand(t3, kIntSize)); // exponent
+ __ sw(t0, MemOperand(t3, Register::kMantissaOffset)); // mantissa
+ __ sw(t1, MemOperand(t3, Register::kExponentOffset)); // exponent
__ Addu(t3, t3, kDoubleSize);
__ bind(&entry);
@@ -773,7 +877,9 @@
__ sw(t5, MemOperand(t2, HeapObject::kMapOffset));
// Prepare for conversion loop.
- __ Addu(t0, t0, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4));
+ __ Addu(t0, t0, Operand(
+ FixedDoubleArray::kHeaderSize - kHeapObjectTag
+ + Register::kExponentOffset));
__ Addu(a3, t2, Operand(FixedArray::kHeaderSize));
__ Addu(t2, t2, Operand(kHeapObjectTag));
__ sll(t1, t1, 1);
@@ -782,7 +888,8 @@
__ LoadRoot(t5, Heap::kHeapNumberMapRootIndex);
// Using offsetted addresses.
// a3: begin of destination FixedArray element fields, not tagged
- // t0: begin of source FixedDoubleArray element fields, not tagged, +4
+ // t0: begin of source FixedDoubleArray element fields, not tagged,
+ // points to the exponent
// t1: end of destination FixedArray, not tagged
// t2: destination FixedArray
// t3: the-hole pointer
@@ -805,7 +912,9 @@
// Non-hole double, copy value into a heap number.
__ AllocateHeapNumber(a2, a0, t6, t5, &gc_required);
// a2: new heap number
- __ lw(a0, MemOperand(t0, -12));
+ // Load mantissa of current element, t0 point to exponent of next element.
+ __ lw(a0, MemOperand(t0, (Register::kMantissaOffset
+ - Register::kExponentOffset - kDoubleSize)));
__ sw(a0, FieldMemOperand(a2, HeapNumber::kMantissaOffset));
__ sw(a1, FieldMemOperand(a2, HeapNumber::kExponentOffset));
__ mov(a0, a3);
@@ -1010,8 +1119,8 @@
__ li(temp3, Operand(ExternalReference::math_exp_log_table()));
__ sll(at, temp2, 3);
__ Addu(temp3, temp3, Operand(at));
- __ lw(temp2, MemOperand(temp3, 0));
- __ lw(temp3, MemOperand(temp3, kPointerSize));
+ __ lw(temp2, MemOperand(temp3, Register::kMantissaOffset));
+ __ lw(temp3, MemOperand(temp3, Register::kExponentOffset));
// The first word is loaded is the lower number register.
if (temp2.code() < temp3.code()) {
__ sll(at, temp1, 20);
diff --git a/src/mips/constants-mips.h b/src/mips/constants-mips.h
index dcf8b82..bf9b5f2 100644
--- a/src/mips/constants-mips.h
+++ b/src/mips/constants-mips.h
@@ -55,6 +55,18 @@
static const ArchVariants kArchVariant = kMips32r1;
#endif
+enum Endianness {
+ kLittle,
+ kBig
+};
+
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+ static const Endianness kArchEndian = kLittle;
+#elif defined(V8_TARGET_BIG_ENDIAN)
+ static const Endianness kArchEndian = kBig;
+#else
+#error Unknown endianness
+#endif
#if(defined(__mips_hard_float) && __mips_hard_float != 0)
// Use floating-point coprocessor instructions. This flag is raised when
@@ -69,6 +81,15 @@
const bool IsMipsSoftFloatABI = true;
#endif
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+const uint32_t kHoleNanUpper32Offset = 4;
+const uint32_t kHoleNanLower32Offset = 0;
+#elif defined(V8_TARGET_BIG_ENDIAN)
+const uint32_t kHoleNanUpper32Offset = 0;
+const uint32_t kHoleNanLower32Offset = 4;
+#else
+#error Unknown endianness
+#endif
// Defines constants and accessor classes to assemble, disassemble and
// simulate MIPS32 instructions.
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index ef6bc84..1466af6 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -2285,7 +2285,7 @@
Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->generator_result_map());
+ Handle<Map> map(isolate()->native_context()->iterator_result_map());
__ Allocate(map->instance_size(), v0, a2, a3, &gc_required, TAG_OBJECT);
__ jmp(&allocated);
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc
index 09ffe95..5114042 100644
--- a/src/mips/ic-mips.cc
+++ b/src/mips/ic-mips.cc
@@ -918,7 +918,7 @@
// We have to see if the double version of the hole is present. If so
// go to the runtime.
__ Addu(address, elements,
- Operand(FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32)
+ Operand(FixedDoubleArray::kHeaderSize + kHoleNanUpper32Offset
- kHeapObjectTag));
__ sll(at, key, kPointerSizeLog2);
__ addu(address, address, at);
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index dd05f7d..b989777 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -3219,7 +3219,7 @@
__ ldc1(result, MemOperand(scratch));
if (instr->hydrogen()->RequiresHoleCheck()) {
- __ lw(scratch, MemOperand(scratch, sizeof(kHoleNanLower32)));
+ __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset));
DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32));
}
}
@@ -4085,7 +4085,7 @@
__ SmiTst(value, scratch);
DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg));
- // We know that value is a smi now, so we can omit the check below.
+ // We know now that value is not a smi, so we can omit the check below.
check_needed = OMIT_SMI_CHECK;
}
} else if (representation.IsDouble()) {
@@ -4162,42 +4162,25 @@
}
-void LCodeGen::ApplyCheckIf(Condition condition,
- LBoundsCheck* check,
- Register src1,
- const Operand& src2) {
- if (FLAG_debug_code && check->hydrogen()->skip_check()) {
+void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
+ Condition cc = instr->hydrogen()->allow_equality() ? hi : hs;
+ Operand operand(0);
+ Register reg;
+ if (instr->index()->IsConstantOperand()) {
+ operand = ToOperand(instr->index());
+ reg = ToRegister(instr->length());
+ cc = ReverseCondition(cc);
+ } else {
+ reg = ToRegister(instr->index());
+ operand = ToOperand(instr->length());
+ }
+ if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
Label done;
- __ Branch(&done, NegateCondition(condition), src1, src2);
+ __ Branch(&done, NegateCondition(cc), reg, operand);
__ stop("eliminated bounds check failed");
__ bind(&done);
} else {
- DeoptimizeIf(condition, check->environment(), src1, src2);
- }
-}
-
-
-void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
- if (instr->hydrogen()->skip_check()) return;
-
- Condition condition = instr->hydrogen()->allow_equality() ? hi : hs;
- if (instr->index()->IsConstantOperand()) {
- int constant_index =
- ToInteger32(LConstantOperand::cast(instr->index()));
- if (instr->hydrogen()->length()->representation().IsSmi()) {
- __ li(at, Operand(Smi::FromInt(constant_index)));
- } else {
- __ li(at, Operand(constant_index));
- }
- ApplyCheckIf(condition,
- instr,
- at,
- Operand(ToRegister(instr->length())));
- } else {
- ApplyCheckIf(condition,
- instr,
- ToRegister(instr->index()),
- Operand(ToRegister(instr->length())));
+ DeoptimizeIf(cc, instr->environment(), reg, operand);
}
}
@@ -5197,13 +5180,13 @@
__ bind(deferred->check_maps());
}
- UniqueSet<Map> map_set = instr->hydrogen()->map_set();
+ const UniqueSet<Map>* map_set = instr->hydrogen()->map_set();
Label success;
- for (int i = 0; i < map_set.size() - 1; i++) {
- Handle<Map> map = map_set.at(i).handle();
+ for (int i = 0; i < map_set->size() - 1; i++) {
+ Handle<Map> map = map_set->at(i).handle();
__ CompareMapAndBranch(map_reg, map, &success, eq, &success);
}
- Handle<Map> map = map_set.at(map_set.size() - 1).handle();
+ Handle<Map> map = map_set->at(map_set->size() - 1).handle();
// Do the CompareMap() directly within the Branch() and DeoptimizeIf().
if (instr->hydrogen()->has_migration_target()) {
__ Branch(deferred->entry(), ne, map_reg, Operand(map));
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index 691559a..890655c 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -263,10 +263,6 @@
LEnvironment* environment,
Register src1 = zero_reg,
const Operand& src2 = Operand(zero_reg));
- void ApplyCheckIf(Condition condition,
- LBoundsCheck* check,
- Register src1 = zero_reg,
- const Operand& src2 = Operand(zero_reg));
void AddToTranslation(LEnvironment* environment,
Translation* translation,
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index e4a7a65..0bfe7d2 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -1626,6 +1626,8 @@
LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
HCompareNumericAndBranch* instr) {
+ LInstruction* goto_instr = CheckElideControlInstruction(instr);
+ if (goto_instr != NULL) return goto_instr;
Representation r = instr->representation();
if (r.IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(r));
@@ -1780,9 +1782,16 @@
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
- LOperand* value = UseRegisterOrConstantAtStart(instr->index());
- LOperand* length = UseRegister(instr->length());
- return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
+ if (!FLAG_debug_code && instr->skip_check()) return NULL;
+ LOperand* index = UseRegisterOrConstantAtStart(instr->index());
+ LOperand* length = !index->IsConstantOperand()
+ ? UseRegisterOrConstantAtStart(instr->length())
+ : UseRegisterAtStart(instr->length());
+ LInstruction* result = new(zone()) LBoundsCheck(index, length);
+ if (!FLAG_debug_code || !instr->skip_check()) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 77c02e7..e345666 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -2091,7 +2091,7 @@
case Uless_equal:
if (rt.imm32_ == 0) {
offset = shifted_branch_offset(L, false);
- b(offset);
+ beq(rs, zero_reg, offset);
} else {
ASSERT(!scratch.is(rs));
r2 = scratch;
@@ -3313,13 +3313,24 @@
// TODO(kalmard) check if this can be optimized to use sw in most cases.
// Can't use unaligned access - copy byte by byte.
- sb(scratch, MemOperand(dst, 0));
- srl(scratch, scratch, 8);
- sb(scratch, MemOperand(dst, 1));
- srl(scratch, scratch, 8);
- sb(scratch, MemOperand(dst, 2));
- srl(scratch, scratch, 8);
- sb(scratch, MemOperand(dst, 3));
+ if (kArchEndian == kLittle) {
+ sb(scratch, MemOperand(dst, 0));
+ srl(scratch, scratch, 8);
+ sb(scratch, MemOperand(dst, 1));
+ srl(scratch, scratch, 8);
+ sb(scratch, MemOperand(dst, 2));
+ srl(scratch, scratch, 8);
+ sb(scratch, MemOperand(dst, 3));
+ } else {
+ sb(scratch, MemOperand(dst, 3));
+ srl(scratch, scratch, 8);
+ sb(scratch, MemOperand(dst, 2));
+ srl(scratch, scratch, 8);
+ sb(scratch, MemOperand(dst, 1));
+ srl(scratch, scratch, 8);
+ sb(scratch, MemOperand(dst, 0));
+ }
+
Addu(dst, dst, 4);
Subu(length, length, Operand(kPointerSize));
@@ -3424,11 +3435,12 @@
bind(&have_double_value);
sll(scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize);
Addu(scratch1, scratch1, elements_reg);
- sw(mantissa_reg, FieldMemOperand(
- scratch1, FixedDoubleArray::kHeaderSize - elements_offset));
- uint32_t offset = FixedDoubleArray::kHeaderSize - elements_offset +
- sizeof(kHoleNanLower32);
- sw(exponent_reg, FieldMemOperand(scratch1, offset));
+ sw(mantissa_reg,
+ FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - elements_offset
+ + kHoleNanLower32Offset));
+ sw(exponent_reg,
+ FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - elements_offset
+ + kHoleNanUpper32Offset));
jmp(&done);
bind(&maybe_nan);
@@ -3526,7 +3538,11 @@
void MacroAssembler::MovFromFloatResult(DoubleRegister dst) {
if (IsMipsSoftFloatABI) {
- Move(dst, v0, v1);
+ if (kArchEndian == kLittle) {
+ Move(dst, v0, v1);
+ } else {
+ Move(dst, v1, v0);
+ }
} else {
Move(dst, f0); // Reg f0 is o32 ABI FP return value.
}
@@ -3535,7 +3551,11 @@
void MacroAssembler::MovFromFloatParameter(DoubleRegister dst) {
if (IsMipsSoftFloatABI) {
- Move(dst, a0, a1);
+ if (kArchEndian == kLittle) {
+ Move(dst, a0, a1);
+ } else {
+ Move(dst, a1, a0);
+ }
} else {
Move(dst, f12); // Reg f12 is o32 ABI FP first argument value.
}
@@ -3546,7 +3566,11 @@
if (!IsMipsSoftFloatABI) {
Move(f12, src);
} else {
- Move(a0, a1, src);
+ if (kArchEndian == kLittle) {
+ Move(a0, a1, src);
+ } else {
+ Move(a1, a0, src);
+ }
}
}
@@ -3555,7 +3579,11 @@
if (!IsMipsSoftFloatABI) {
Move(f0, src);
} else {
- Move(v0, v1, src);
+ if (kArchEndian == kLittle) {
+ Move(v0, v1, src);
+ } else {
+ Move(v1, v0, src);
+ }
}
}
@@ -3572,8 +3600,13 @@
Move(f14, src2);
}
} else {
- Move(a0, a1, src1);
- Move(a2, a3, src2);
+ if (kArchEndian == kLittle) {
+ Move(a0, a1, src1);
+ Move(a2, a3, src2);
+ } else {
+ Move(a1, a0, src1);
+ Move(a3, a2, src2);
+ }
}
}
diff --git a/src/mips/regexp-macro-assembler-mips.cc b/src/mips/regexp-macro-assembler-mips.cc
index 49dec3c..6ca8a3d 100644
--- a/src/mips/regexp-macro-assembler-mips.cc
+++ b/src/mips/regexp-macro-assembler-mips.cc
@@ -1153,7 +1153,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
+ Object* result = Execution::HandleStackGuardInterrupt(isolate);
if (*code_handle != re_code) { // Return address no longer valid.
int delta = code_handle->address() - re_code->address();
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 153a816..59dc905 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -416,6 +416,24 @@
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
+ HeapType* field_type = descriptors->GetFieldType(descriptor);
+ HeapType::Iterator<Map> it = field_type->Classes();
+ Handle<Map> current;
+ if (!it.Done()) {
+ __ lw(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
+ Label do_store;
+ while (true) {
+ // Do the CompareMap() directly within the Branch() functions.
+ current = it.Current();
+ it.Advance();
+ if (it.Done()) {
+ __ Branch(miss_label, ne, scratch1, Operand(current));
+ break;
+ }
+ __ Branch(&do_store, eq, scratch1, Operand(current));
+ }
+ __ bind(&do_store);
+ }
} else if (representation.IsDouble()) {
Label do_store, heap_number;
__ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
@@ -579,6 +597,24 @@
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
+ HeapType* field_type = lookup->GetFieldType();
+ HeapType::Iterator<Map> it = field_type->Classes();
+ if (!it.Done()) {
+ __ lw(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
+ Label do_store;
+ Handle<Map> current;
+ while (true) {
+ // Do the CompareMap() directly within the Branch() functions.
+ current = it.Current();
+ it.Advance();
+ if (it.Done()) {
+ __ Branch(miss_label, ne, scratch1, Operand(current));
+ break;
+ }
+ __ Branch(&do_store, eq, scratch1, Operand(current));
+ }
+ __ bind(&do_store);
+ }
} else if (representation.IsDouble()) {
// Load the double storage.
if (index < 0) {
@@ -824,7 +860,9 @@
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
- if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
+ if (type->IsConstant()) {
+ current = Handle<JSObject>::cast(type->AsConstant()->Value());
+ }
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> holder_map(holder->map());
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index 07b0575..47b5b3c 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -41,6 +41,10 @@
#include "serialize.h"
#include "list.h"
+#if V8_TARGET_ARCH_ARM
+#include "arm/assembler-arm-inl.h"
+#endif
+
using namespace v8;
@@ -272,6 +276,12 @@
// By default, log code create information in the snapshot.
i::FLAG_log_code = true;
+#if V8_TARGET_ARCH_ARM
+ // Printing flags on ARM requires knowing if we intend to enable
+ // the serializer or not.
+ v8::internal::CpuFeatures::SetHintCreatingSnapshot();
+#endif
+
// Print the usage if an error occurs when parsing the command line
// flags or if the help flag is set.
int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
@@ -293,7 +303,7 @@
Isolate* isolate = v8::Isolate::New();
isolate->Enter();
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- i::Serializer::Enable(internal_isolate);
+ i::Serializer::RequestEnable(internal_isolate);
Persistent<Context> context;
{
HandleScope handle_scope(isolate);
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index bacf422..13026ed 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -170,6 +170,12 @@
case JS_MAP_TYPE:
JSMap::cast(this)->JSMapVerify();
break;
+ case JS_SET_ITERATOR_TYPE:
+ JSSetIterator::cast(this)->JSSetIteratorVerify();
+ break;
+ case JS_MAP_ITERATOR_TYPE:
+ JSMapIterator::cast(this)->JSMapIteratorVerify();
+ break;
case JS_WEAK_MAP_TYPE:
JSWeakMap::cast(this)->JSWeakMapVerify();
break;
@@ -299,6 +305,12 @@
if (value->IsUninitialized()) continue;
if (r.IsSmi()) ASSERT(value->IsSmi());
if (r.IsHeapObject()) ASSERT(value->IsHeapObject());
+ HeapType* field_type = descriptors->GetFieldType(i);
+ if (r.IsNone()) {
+ CHECK(field_type->Is(HeapType::None()));
+ } else if (!HeapType::Any()->Is(field_type)) {
+ CHECK(!field_type->NowStable() || field_type->NowContains(value));
+ }
}
}
}
@@ -606,7 +618,7 @@
CHECK(number->IsSmi());
int value = Smi::cast(number)->value();
// Hidden oddballs have negative smis.
- const int kLeastHiddenOddballNumber = -4;
+ const int kLeastHiddenOddballNumber = -5;
CHECK_LE(value, 1);
CHECK(value >= kLeastHiddenOddballNumber);
}
@@ -627,6 +639,8 @@
CHECK(this == heap->arguments_marker());
} else if (map() == heap->termination_exception_map()) {
CHECK(this == heap->termination_exception());
+ } else if (map() == heap->exception_map()) {
+ CHECK(this == heap->exception());
} else {
UNREACHABLE();
}
@@ -702,6 +716,7 @@
JSObjectVerify();
VerifyHeapPointer(table());
CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
+ // TODO(arv): Verify OrderedHashTable too.
}
@@ -710,6 +725,39 @@
JSObjectVerify();
VerifyHeapPointer(table());
CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
+ // TODO(arv): Verify OrderedHashTable too.
+}
+
+
+void JSSetIterator::JSSetIteratorVerify() {
+ CHECK(IsJSSetIterator());
+ JSObjectVerify();
+ VerifyHeapPointer(table());
+ CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
+ CHECK(index()->IsSmi());
+ CHECK(count()->IsSmi());
+ CHECK(kind()->IsSmi());
+ VerifyHeapPointer(next_iterator());
+ CHECK(next_iterator()->IsJSSetIterator() || next_iterator()->IsUndefined());
+ VerifyHeapPointer(table());
+ CHECK(previous_iterator()->IsJSSetIterator()
+ || previous_iterator()->IsUndefined());
+}
+
+
+void JSMapIterator::JSMapIteratorVerify() {
+ CHECK(IsJSMapIterator());
+ JSObjectVerify();
+ VerifyHeapPointer(table());
+ CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
+ CHECK(index()->IsSmi());
+ CHECK(count()->IsSmi());
+ CHECK(kind()->IsSmi());
+ VerifyHeapPointer(next_iterator());
+ CHECK(next_iterator()->IsJSMapIterator() || next_iterator()->IsUndefined());
+ VerifyHeapPointer(table());
+ CHECK(previous_iterator()->IsJSMapIterator()
+ || previous_iterator()->IsUndefined());
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index c44232e..68bd159 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -87,13 +87,6 @@
}
-#define FIXED_TYPED_ARRAY_CAST_ACCESSOR(type) \
- template<> \
- type* type::cast(Object* object) { \
- SLOW_ASSERT(object->Is##type()); \
- return reinterpret_cast<type*>(object); \
- }
-
#define INT_ACCESSORS(holder, name, offset) \
int holder::name() { return READ_INT_FIELD(this, offset); } \
void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
@@ -286,6 +279,7 @@
String::cast(this)->IsTwoByteRepresentation();
}
+
bool Object::HasValidElements() {
// Dictionary is covered under FixedArray.
return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray() ||
@@ -293,16 +287,17 @@
}
-MaybeObject* Object::AllocateNewStorageFor(Heap* heap,
- Representation representation) {
- if (representation.IsSmi() && IsUninitialized()) {
- return Smi::FromInt(0);
+Handle<Object> Object::NewStorageFor(Isolate* isolate,
+ Handle<Object> object,
+ Representation representation) {
+ if (representation.IsSmi() && object->IsUninitialized()) {
+ return handle(Smi::FromInt(0), isolate);
}
- if (!representation.IsDouble()) return this;
- if (IsUninitialized()) {
- return heap->AllocateHeapNumber(0);
+ if (!representation.IsDouble()) return object;
+ if (object->IsUninitialized()) {
+ return isolate->factory()->NewHeapNumber(0);
}
- return heap->AllocateHeapNumber(Number());
+ return isolate->factory()->NewHeapNumber(object->Number());
}
@@ -671,16 +666,6 @@
}
-bool MaybeObject::IsTheHole() {
- return !IsFailure() && ToObjectUnchecked()->IsTheHole();
-}
-
-
-bool MaybeObject::IsUninitialized() {
- return !IsFailure() && ToObjectUnchecked()->IsUninitialized();
-}
-
-
Failure* Failure::cast(MaybeObject* obj) {
ASSERT(HAS_FAILURE_TAG(obj));
return reinterpret_cast<Failure*>(obj);
@@ -711,6 +696,8 @@
TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
TYPE_CHECKER(JSSet, JS_SET_TYPE)
TYPE_CHECKER(JSMap, JS_MAP_TYPE)
+TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
+TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
@@ -1015,6 +1002,11 @@
}
+bool Object::IsException() {
+ return IsOddball() && Oddball::cast(this)->kind() == Oddball::kException;
+}
+
+
bool Object::IsUninitialized() {
return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUninitialized;
}
@@ -1061,20 +1053,6 @@
}
-// TODO(ishell): Use handlified version instead.
-MaybeObject* Object::ToSmi() {
- if (IsSmi()) return this;
- if (IsHeapNumber()) {
- double value = HeapNumber::cast(this)->value();
- int int_value = FastD2I(value);
- if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
- return Smi::FromInt(int_value);
- }
- }
- return Failure::Exception();
-}
-
-
MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
Handle<Object> object) {
return ToObject(
@@ -1114,6 +1092,19 @@
}
+MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
+ Handle<Object> object,
+ const char* name) {
+ Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
+ ASSERT(!str.is_null());
+#ifdef DEBUG
+ uint32_t index; // Assert that the name is not an array index.
+ ASSERT(!str->AsArrayIndex(&index));
+#endif // DEBUG
+ return GetProperty(object, str);
+}
+
+
MaybeHandle<Object> JSProxy::GetElementWithHandler(Handle<JSProxy> proxy,
Handle<Object> receiver,
uint32_t index) {
@@ -1299,11 +1290,6 @@
}
-bool Failure::IsInternalError() const {
- return type() == INTERNAL_ERROR;
-}
-
-
AllocationSpace Failure::allocation_space() const {
ASSERT_EQ(RETRY_AFTER_GC, type());
return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
@@ -1923,6 +1909,10 @@
return JSSet::kSize;
case JS_MAP_TYPE:
return JSMap::kSize;
+ case JS_SET_ITERATOR_TYPE:
+ return JSSetIterator::kSize;
+ case JS_MAP_ITERATOR_TYPE:
+ return JSMapIterator::kSize;
case JS_WEAK_MAP_TYPE:
return JSWeakMap::kSize;
case JS_WEAK_SET_TYPE:
@@ -1987,13 +1977,6 @@
}
-MaybeObject* JSObject::FastPropertyAt(Representation representation,
- int index) {
- Object* raw_value = RawFastPropertyAt(index);
- return raw_value->AllocateNewStorageFor(GetHeap(), representation);
-}
-
-
// Access fast-case object properties at index. The use of these routines
// is needed to correctly distinguish between properties stored in-object and
// properties stored in the properties array.
@@ -2227,14 +2210,6 @@
return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize);
}
-MaybeObject* FixedDoubleArray::get(int index) {
- if (is_the_hole(index)) {
- return GetHeap()->the_hole_value();
- } else {
- return GetHeap()->NumberFromDouble(get_scalar(index));
- }
-}
-
Handle<Object> FixedDoubleArray::get(Handle<FixedDoubleArray> array,
int index) {
@@ -2729,14 +2704,6 @@
}
-void DescriptorArray::InitializeRepresentations(Representation representation) {
- int length = number_of_descriptors();
- for (int i = 0; i < length; i++) {
- SetRepresentation(i, representation);
- }
-}
-
-
Object** DescriptorArray::GetValueSlot(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors());
return RawFieldOfElementAt(ToValueIndex(descriptor_number));
@@ -2749,6 +2716,11 @@
}
+void DescriptorArray::SetValue(int descriptor_index, Object* value) {
+ set(ToValueIndex(descriptor_index), value);
+}
+
+
PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors());
Object* details = get(ToDetailsIndex(descriptor_number));
@@ -2767,6 +2739,12 @@
}
+HeapType* DescriptorArray::GetFieldType(int descriptor_number) {
+ ASSERT(GetDetails(descriptor_number).type() == FIELD);
+ return HeapType::cast(GetValue(descriptor_number));
+}
+
+
Object* DescriptorArray::GetConstant(int descriptor_number) {
return GetValue(descriptor_number);
}
@@ -2995,6 +2973,8 @@
CAST_ACCESSOR(JSFunctionProxy)
CAST_ACCESSOR(JSSet)
CAST_ACCESSOR(JSMap)
+CAST_ACCESSOR(JSSetIterator)
+CAST_ACCESSOR(JSMapIterator)
CAST_ACCESSOR(JSWeakMap)
CAST_ACCESSOR(JSWeakSet)
CAST_ACCESSOR(Foreign)
@@ -3638,15 +3618,11 @@
}
-Object* ExternalUint8ClampedArray::get(int index) {
- return Smi::FromInt(static_cast<int>(get_scalar(index)));
-}
-
-
Handle<Object> ExternalUint8ClampedArray::get(
Handle<ExternalUint8ClampedArray> array,
int index) {
- return handle(array->get(index), array->GetIsolate());
+ return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
+ array->GetIsolate());
}
@@ -3676,14 +3652,10 @@
}
-Object* ExternalInt8Array::get(int index) {
- return Smi::FromInt(static_cast<int>(get_scalar(index)));
-}
-
-
Handle<Object> ExternalInt8Array::get(Handle<ExternalInt8Array> array,
int index) {
- return handle(array->get(index), array->GetIsolate());
+ return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
+ array->GetIsolate());
}
@@ -3701,14 +3673,10 @@
}
-Object* ExternalUint8Array::get(int index) {
- return Smi::FromInt(static_cast<int>(get_scalar(index)));
-}
-
-
Handle<Object> ExternalUint8Array::get(Handle<ExternalUint8Array> array,
int index) {
- return handle(array->get(index), array->GetIsolate());
+ return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
+ array->GetIsolate());
}
@@ -3726,14 +3694,10 @@
}
-Object* ExternalInt16Array::get(int index) {
- return Smi::FromInt(static_cast<int>(get_scalar(index)));
-}
-
-
Handle<Object> ExternalInt16Array::get(Handle<ExternalInt16Array> array,
int index) {
- return handle(array->get(index), array->GetIsolate());
+ return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
+ array->GetIsolate());
}
@@ -3751,14 +3715,10 @@
}
-Object* ExternalUint16Array::get(int index) {
- return Smi::FromInt(static_cast<int>(get_scalar(index)));
-}
-
-
Handle<Object> ExternalUint16Array::get(Handle<ExternalUint16Array> array,
int index) {
- return handle(array->get(index), array->GetIsolate());
+ return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
+ array->GetIsolate());
}
@@ -3776,11 +3736,6 @@
}
-MaybeObject* ExternalInt32Array::get(int index) {
- return GetHeap()->NumberFromInt32(get_scalar(index));
-}
-
-
Handle<Object> ExternalInt32Array::get(Handle<ExternalInt32Array> array,
int index) {
return array->GetIsolate()->factory()->
@@ -3802,11 +3757,6 @@
}
-MaybeObject* ExternalUint32Array::get(int index) {
- return GetHeap()->NumberFromUint32(get_scalar(index));
-}
-
-
Handle<Object> ExternalUint32Array::get(Handle<ExternalUint32Array> array,
int index) {
return array->GetIsolate()->factory()->
@@ -3828,11 +3778,6 @@
}
-MaybeObject* ExternalFloat32Array::get(int index) {
- return GetHeap()->NumberFromDouble(get_scalar(index));
-}
-
-
Handle<Object> ExternalFloat32Array::get(Handle<ExternalFloat32Array> array,
int index) {
return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
@@ -3853,11 +3798,6 @@
}
-MaybeObject* ExternalFloat64Array::get(int index) {
- return GetHeap()->NumberFromDouble(get_scalar(index));
-}
-
-
Handle<Object> ExternalFloat64Array::get(Handle<ExternalFloat64Array> array,
int index) {
return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
@@ -4005,50 +3945,34 @@
template <class Traits>
-MaybeObject* FixedTypedArray<Traits>::get(int index) {
- return Traits::ToObject(GetHeap(), get_scalar(index));
-}
-
-template <class Traits>
Handle<Object> FixedTypedArray<Traits>::get(
Handle<FixedTypedArray<Traits> > array,
int index) {
return Traits::ToHandle(array->GetIsolate(), array->get_scalar(index));
}
-template <class Traits>
-MaybeObject* FixedTypedArray<Traits>::SetValue(uint32_t index, Object* value) {
- ElementType cast_value = Traits::defaultValue();
- if (index < static_cast<uint32_t>(length())) {
- if (value->IsSmi()) {
- int int_value = Smi::cast(value)->value();
- cast_value = from_int(int_value);
- } else if (value->IsHeapNumber()) {
- double double_value = HeapNumber::cast(value)->value();
- cast_value = from_double(double_value);
- } else {
- // Clamp undefined to the default value. All other types have been
- // converted to a number type further up in the call chain.
- ASSERT(value->IsUndefined());
- }
- set(index, cast_value);
- }
- return Traits::ToObject(GetHeap(), cast_value);
-}
template <class Traits>
Handle<Object> FixedTypedArray<Traits>::SetValue(
Handle<FixedTypedArray<Traits> > array,
uint32_t index,
Handle<Object> value) {
- CALL_HEAP_FUNCTION(array->GetIsolate(),
- array->SetValue(index, *value),
- Object);
-}
-
-
-MaybeObject* Uint8ArrayTraits::ToObject(Heap*, uint8_t scalar) {
- return Smi::FromInt(scalar);
+ ElementType cast_value = Traits::defaultValue();
+ if (index < static_cast<uint32_t>(array->length())) {
+ if (value->IsSmi()) {
+ int int_value = Handle<Smi>::cast(value)->value();
+ cast_value = from_int(int_value);
+ } else if (value->IsHeapNumber()) {
+ double double_value = Handle<HeapNumber>::cast(value)->value();
+ cast_value = from_double(double_value);
+ } else {
+ // Clamp undefined to the default value. All other types have been
+ // converted to a number type further up in the call chain.
+ ASSERT(value->IsUndefined());
+ }
+ array->set(index, cast_value);
+ }
+ return Traits::ToHandle(array->GetIsolate(), cast_value);
}
@@ -4057,82 +3981,42 @@
}
-MaybeObject* Uint8ClampedArrayTraits::ToObject(Heap*, uint8_t scalar) {
- return Smi::FromInt(scalar);
-}
-
-
Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
uint8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
-MaybeObject* Int8ArrayTraits::ToObject(Heap*, int8_t scalar) {
- return Smi::FromInt(scalar);
-}
-
-
Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
-MaybeObject* Uint16ArrayTraits::ToObject(Heap*, uint16_t scalar) {
- return Smi::FromInt(scalar);
-}
-
-
Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
-MaybeObject* Int16ArrayTraits::ToObject(Heap*, int16_t scalar) {
- return Smi::FromInt(scalar);
-}
-
-
Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
-MaybeObject* Uint32ArrayTraits::ToObject(Heap* heap, uint32_t scalar) {
- return heap->NumberFromUint32(scalar);
-}
-
-
Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
return isolate->factory()->NewNumberFromUint(scalar);
}
-MaybeObject* Int32ArrayTraits::ToObject(Heap* heap, int32_t scalar) {
- return heap->NumberFromInt32(scalar);
-}
-
-
Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
return isolate->factory()->NewNumberFromInt(scalar);
}
-MaybeObject* Float32ArrayTraits::ToObject(Heap* heap, float scalar) {
- return heap->NumberFromDouble(scalar);
-}
-
-
Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
return isolate->factory()->NewNumber(scalar);
}
-MaybeObject* Float64ArrayTraits::ToObject(Heap* heap, double scalar) {
- return heap->NumberFromDouble(scalar);
-}
-
-
Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
return isolate->factory()->NewNumber(scalar);
}
@@ -5315,7 +5199,6 @@
ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
-SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset)
@@ -5370,6 +5253,8 @@
SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
kOptCountAndBailoutReasonOffset)
SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset)
+SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
+SMI_ACCESSORS(SharedFunctionInfo, profiler_ticks, kProfilerTicksOffset)
#else
@@ -5420,9 +5305,15 @@
PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
opt_count_and_bailout_reason,
kOptCountAndBailoutReasonOffset)
-
PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset)
+PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
+ ast_node_count,
+ kAstNodeCountOffset)
+PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
+ profiler_ticks,
+ kProfilerTicksOffset)
+
#endif
@@ -5466,12 +5357,6 @@
}
-int SharedFunctionInfo::profiler_ticks() {
- if (code()->kind() != Code::FUNCTION) return 0;
- return code()->profiler_ticks();
-}
-
-
StrictMode SharedFunctionInfo::strict_mode() {
return BooleanBit::get(compiler_hints(), kStrictModeFunction)
? STRICT : SLOPPY;
@@ -5922,6 +5807,32 @@
ACCESSORS(JSSet, table, Object, kTableOffset)
ACCESSORS(JSMap, table, Object, kTableOffset)
+
+
+#define ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(name, type, offset) \
+ template<class Derived, class TableType> \
+ type* OrderedHashTableIterator<Derived, TableType>::name() { \
+ return type::cast(READ_FIELD(this, offset)); \
+ } \
+ template<class Derived, class TableType> \
+ void OrderedHashTableIterator<Derived, TableType>::set_##name( \
+ type* value, WriteBarrierMode mode) { \
+ WRITE_FIELD(this, offset, value); \
+ CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
+ }
+
+ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(table, Object, kTableOffset)
+ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(index, Smi, kIndexOffset)
+ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(count, Smi, kCountOffset)
+ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(kind, Smi, kKindOffset)
+ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(next_iterator, Object,
+ kNextIteratorOffset)
+ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(previous_iterator, Object,
+ kPreviousIteratorOffset)
+
+#undef ORDERED_HASH_TABLE_ITERATOR_ACCESSORS
+
+
ACCESSORS(JSWeakCollection, table, Object, kTableOffset)
ACCESSORS(JSWeakCollection, next, Object, kNextOffset)
@@ -6361,6 +6272,20 @@
}
+Handle<JSSetIterator> JSSetIterator::Create(
+ Handle<OrderedHashSet> table,
+ int kind) {
+ return CreateInternal(table->GetIsolate()->set_iterator_map(), table, kind);
+}
+
+
+Handle<JSMapIterator> JSMapIterator::Create(
+ Handle<OrderedHashMap> table,
+ int kind) {
+ return CreateInternal(table->GetIsolate()->map_iterator_map(), table, kind);
+}
+
+
bool Name::IsHashFieldComputed(uint32_t field) {
return (field & kHashNotComputedMask) == 0;
}
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index a59b1e9..f948399 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -174,6 +174,12 @@
case JS_MAP_TYPE:
JSMap::cast(this)->JSMapPrint(out);
break;
+ case JS_SET_ITERATOR_TYPE:
+ JSSetIterator::cast(this)->JSSetIteratorPrint(out);
+ break;
+ case JS_MAP_ITERATOR_TYPE:
+ JSMapIterator::cast(this)->JSMapIteratorPrint(out);
+ break;
case JS_WEAK_MAP_TYPE:
JSWeakMap::cast(this)->JSWeakMapPrint(out);
break;
@@ -722,7 +728,7 @@
PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
PrintF(out, " - handler = ");
handler()->Print(out);
- PrintF(out, " - hash = ");
+ PrintF(out, "\n - hash = ");
hash()->Print(out);
PrintF(out, "\n");
}
@@ -733,9 +739,9 @@
PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
PrintF(out, " - handler = ");
handler()->Print(out);
- PrintF(out, " - call_trap = ");
+ PrintF(out, "\n - call_trap = ");
call_trap()->Print(out);
- PrintF(out, " - construct_trap = ");
+ PrintF(out, "\n - construct_trap = ");
construct_trap()->Print(out);
PrintF(out, "\n");
}
@@ -759,6 +765,48 @@
}
+template<class Derived, class TableType>
+void OrderedHashTableIterator<Derived, TableType>::
+ OrderedHashTableIteratorPrint(FILE* out) {
+ PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
+ PrintF(out, " - table = ");
+ table()->ShortPrint(out);
+ PrintF(out, "\n - index = ");
+ index()->ShortPrint(out);
+ PrintF(out, "\n - count = ");
+ count()->ShortPrint(out);
+ PrintF(out, "\n - kind = ");
+ kind()->ShortPrint(out);
+ PrintF(out, "\n - next_iterator = ");
+ next_iterator()->ShortPrint(out);
+ PrintF(out, "\n - previous_iterator = ");
+ previous_iterator()->ShortPrint(out);
+ PrintF(out, "\n");
+}
+
+
+template void
+OrderedHashTableIterator<JSSetIterator,
+ OrderedHashSet>::OrderedHashTableIteratorPrint(FILE* out);
+
+
+template void
+OrderedHashTableIterator<JSMapIterator,
+ OrderedHashMap>::OrderedHashTableIteratorPrint(FILE* out);
+
+
+void JSSetIterator::JSSetIteratorPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "JSSetIterator");
+ OrderedHashTableIteratorPrint(out);
+}
+
+
+void JSMapIterator::JSMapIteratorPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "JSMapIterator");
+ OrderedHashTableIteratorPrint(out);
+}
+
+
void JSWeakMap::JSWeakMapPrint(FILE* out) {
HeapObject::PrintHeader(out, "JSWeakMap");
PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
diff --git a/src/objects-visiting.cc b/src/objects-visiting.cc
index b314a47..89de85c 100644
--- a/src/objects-visiting.cc
+++ b/src/objects-visiting.cc
@@ -163,6 +163,8 @@
case JS_GLOBAL_OBJECT_TYPE:
case JS_BUILTINS_OBJECT_TYPE:
case JS_MESSAGE_OBJECT_TYPE:
+ case JS_SET_ITERATOR_TYPE:
+ case JS_MAP_ITERATOR_TYPE:
return GetVisitorIdForSize(kVisitJSObject,
kVisitJSObjectGeneric,
instance_size);
diff --git a/src/objects.cc b/src/objects.cc
index 3342a5f..6a79315 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -49,6 +49,7 @@
#include "macro-assembler.h"
#include "mark-compact.h"
#include "safepoint-table.h"
+#include "string-search.h"
#include "string-stream.h"
#include "utils.h"
@@ -60,6 +61,24 @@
namespace v8 {
namespace internal {
+Handle<HeapType> Object::OptimalType(Isolate* isolate,
+ Representation representation) {
+ if (representation.IsNone()) return HeapType::None(isolate);
+ if (FLAG_track_field_types) {
+ if (representation.IsHeapObject() && IsHeapObject()) {
+ // We can track only JavaScript objects with stable maps.
+ Handle<Map> map(HeapObject::cast(this)->map(), isolate);
+ if (map->is_stable() &&
+ map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
+ map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) {
+ return HeapType::Class(map, isolate);
+ }
+ }
+ }
+ return HeapType::Any(isolate);
+}
+
+
MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
Handle<Object> object,
Handle<Context> native_context) {
@@ -210,9 +229,9 @@
}
-static MaybeObject* PerformCompare(const BitmaskCompareDescriptor& descriptor,
- char* ptr,
- Heap* heap) {
+static Handle<Object> PerformCompare(const BitmaskCompareDescriptor& descriptor,
+ char* ptr,
+ Isolate* isolate) {
uint32_t bitmask = descriptor.bitmask;
uint32_t compare_value = descriptor.compare_value;
uint32_t value;
@@ -232,26 +251,27 @@
break;
default:
UNREACHABLE();
- return NULL;
+ return isolate->factory()->undefined_value();
}
- return heap->ToBoolean((bitmask & value) == (bitmask & compare_value));
+ return isolate->factory()->ToBoolean(
+ (bitmask & value) == (bitmask & compare_value));
}
-static MaybeObject* PerformCompare(const PointerCompareDescriptor& descriptor,
- char* ptr,
- Heap* heap) {
+static Handle<Object> PerformCompare(const PointerCompareDescriptor& descriptor,
+ char* ptr,
+ Isolate* isolate) {
uintptr_t compare_value =
reinterpret_cast<uintptr_t>(descriptor.compare_value);
uintptr_t value = *CheckedCast<uintptr_t>(ptr);
- return heap->ToBoolean(compare_value == value);
+ return isolate->factory()->ToBoolean(compare_value == value);
}
-static MaybeObject* GetPrimitiveValue(
+static Handle<Object> GetPrimitiveValue(
const PrimitiveValueDescriptor& descriptor,
char* ptr,
- Heap* heap) {
+ Isolate* isolate) {
int32_t int32_value = 0;
switch (descriptor.data_type) {
case kDescriptorInt8Type:
@@ -271,29 +291,36 @@
break;
case kDescriptorUint32Type: {
uint32_t value = *CheckedCast<uint32_t>(ptr);
- return heap->NumberFromUint32(value);
+ AllowHeapAllocation allow_gc;
+ return isolate->factory()->NewNumberFromUint(value);
}
case kDescriptorBoolType: {
uint8_t byte = *CheckedCast<uint8_t>(ptr);
- return heap->ToBoolean(byte & (0x1 << descriptor.bool_offset));
+ return isolate->factory()->ToBoolean(
+ byte & (0x1 << descriptor.bool_offset));
}
case kDescriptorFloatType: {
float value = *CheckedCast<float>(ptr);
- return heap->NumberFromDouble(value);
+ AllowHeapAllocation allow_gc;
+ return isolate->factory()->NewNumber(value);
}
case kDescriptorDoubleType: {
double value = *CheckedCast<double>(ptr);
- return heap->NumberFromDouble(value);
+ AllowHeapAllocation allow_gc;
+ return isolate->factory()->NewNumber(value);
}
}
- return heap->NumberFromInt32(int32_value);
+ AllowHeapAllocation allow_gc;
+ return isolate->factory()->NewNumberFromInt(int32_value);
}
-static MaybeObject* GetDeclaredAccessorProperty(Object* receiver,
- DeclaredAccessorInfo* info,
- Isolate* isolate) {
- char* current = reinterpret_cast<char*>(receiver);
+static Handle<Object> GetDeclaredAccessorProperty(
+ Handle<Object> receiver,
+ Handle<DeclaredAccessorInfo> info,
+ Isolate* isolate) {
+ DisallowHeapAllocation no_gc;
+ char* current = reinterpret_cast<char*>(*receiver);
DeclaredAccessorDescriptorIterator iterator(info->descriptor());
while (true) {
const DeclaredAccessorDescriptorData* data = iterator.Next();
@@ -301,7 +328,7 @@
case kDescriptorReturnObject: {
ASSERT(iterator.Complete());
current = *CheckedCast<char*>(current);
- return *CheckedCast<Object*>(current);
+ return handle(*CheckedCast<Object*>(current), isolate);
}
case kDescriptorPointerDereference:
ASSERT(!iterator.Complete());
@@ -324,31 +351,21 @@
ASSERT(iterator.Complete());
return PerformCompare(data->bitmask_compare_descriptor,
current,
- isolate->heap());
+ isolate);
case kDescriptorPointerCompare:
ASSERT(iterator.Complete());
return PerformCompare(data->pointer_compare_descriptor,
current,
- isolate->heap());
+ isolate);
case kDescriptorPrimitiveValue:
ASSERT(iterator.Complete());
return GetPrimitiveValue(data->primitive_value_descriptor,
current,
- isolate->heap());
+ isolate);
}
}
UNREACHABLE();
- return NULL;
-}
-
-
-static Handle<Object> GetDeclaredAccessorProperty(
- Handle<Object> receiver,
- Handle<DeclaredAccessorInfo> info,
- Isolate* isolate) {
- CALL_HEAP_FUNCTION(isolate,
- GetDeclaredAccessorProperty(*receiver, *info, isolate),
- Object);
+ return isolate->factory()->undefined_value();
}
@@ -392,12 +409,10 @@
// so we do not support it for now.
if (name->IsSymbol()) return isolate->factory()->undefined_value();
if (structure->IsDeclaredAccessorInfo()) {
- CALL_HEAP_FUNCTION(
- isolate,
- GetDeclaredAccessorProperty(*receiver,
- DeclaredAccessorInfo::cast(*structure),
- isolate),
- Object);
+ return GetDeclaredAccessorProperty(
+ receiver,
+ Handle<DeclaredAccessorInfo>::cast(structure),
+ isolate);
}
Handle<ExecutableAccessorInfo> data =
@@ -406,10 +421,9 @@
v8::ToCData<v8::AccessorGetterCallback>(data->getter());
if (call_fun == NULL) return isolate->factory()->undefined_value();
- Handle<JSObject> self = Handle<JSObject>::cast(receiver);
Handle<String> key = Handle<String>::cast(name);
- LOG(isolate, ApiNamedPropertyAccess("load", *self, *name));
- PropertyCallbackArguments args(isolate, data->data(), *self, *object);
+ LOG(isolate, ApiNamedPropertyAccess("load", *object, *name));
+ PropertyCallbackArguments args(isolate, data->data(), *receiver, *object);
v8::Handle<v8::Value> result =
args.Call(call_fun, v8::Utils::ToLocal(key));
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
@@ -525,7 +539,7 @@
// No accessible property found.
*attributes = ABSENT;
isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->undefined_value();
}
@@ -870,7 +884,7 @@
if (js_object->IsAccessCheckNeeded()) {
if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->undefined_value();
}
}
@@ -894,6 +908,7 @@
Object* Object::GetPrototype(Isolate* isolate) {
+ DisallowHeapAllocation no_alloc;
if (IsSmi()) {
Context* context = isolate->context()->native_context();
return context->number_function()->instance_prototype();
@@ -925,6 +940,12 @@
}
+Handle<Object> Object::GetPrototype(Isolate* isolate,
+ Handle<Object> object) {
+ return handle(object->GetPrototype(isolate), isolate);
+}
+
+
Map* Object::GetMarkerMap(Isolate* isolate) {
if (IsSmi()) return isolate->heap()->heap_number_map();
return HeapObject::cast(this)->map();
@@ -1402,7 +1423,9 @@
int descriptors,
bool constant_to_field,
Representation old_representation,
- Representation new_representation) {
+ Representation new_representation,
+ HeapType* old_field_type,
+ HeapType* new_field_type) {
PrintF(file, "[generalizing ");
constructor_name()->PrintOn(file);
PrintF(file, "] ");
@@ -1412,13 +1435,19 @@
} else {
PrintF(file, "{symbol %p}", static_cast<void*>(name));
}
+ PrintF(file, ":");
if (constant_to_field) {
- PrintF(file, ":c->f");
+ PrintF(file, "c");
} else {
- PrintF(file, ":%s->%s",
- old_representation.Mnemonic(),
- new_representation.Mnemonic());
+ PrintF(file, "%s", old_representation.Mnemonic());
+ PrintF(file, "{");
+ old_field_type->TypePrint(file, HeapType::SEMANTIC_DIM);
+ PrintF(file, "}");
}
+ PrintF(file, "->%s", new_representation.Mnemonic());
+ PrintF(file, "{");
+ new_field_type->TypePrint(file, HeapType::SEMANTIC_DIM);
+ PrintF(file, "}");
PrintF(file, " (");
if (strlen(reason) > 0) {
PrintF(file, "%s", reason);
@@ -1647,6 +1676,8 @@
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
+ case JS_SET_ITERATOR_TYPE:
+ case JS_MAP_ITERATOR_TYPE:
case JS_WEAK_MAP_TYPE:
case JS_WEAK_SET_TYPE:
case JS_REGEXP_TYPE:
@@ -1796,14 +1827,59 @@
}
-// TODO(mstarzinger): Temporary wrapper until handlified.
-static Handle<Object> NewStorageFor(Isolate* isolate,
- Handle<Object> object,
- Representation representation) {
- Heap* heap = isolate->heap();
- CALL_HEAP_FUNCTION(isolate,
- object->AllocateNewStorageFor(heap, representation),
- Object);
+MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
+ Handle<Name> name,
+ Handle<HeapType> type,
+ PropertyAttributes attributes,
+ Representation representation,
+ TransitionFlag flag) {
+ ASSERT(DescriptorArray::kNotFound ==
+ map->instance_descriptors()->Search(
+ *name, map->NumberOfOwnDescriptors()));
+
+ // Ensure the descriptor array does not get too big.
+ if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
+ return MaybeHandle<Map>();
+ }
+
+ // Normalize the object if the name is an actual name (not the
+ // hidden strings) and is not a real identifier.
+ // Normalize the object if it will have too many fast properties.
+ Isolate* isolate = map->GetIsolate();
+ if (!name->IsCacheable(isolate)) return MaybeHandle<Map>();
+
+ // Compute the new index for new field.
+ int index = map->NextFreePropertyIndex();
+
+ if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
+ representation = Representation::Tagged();
+ type = HeapType::Any(isolate);
+ }
+
+ FieldDescriptor new_field_desc(name, index, type, attributes, representation);
+ Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
+ int unused_property_fields = new_map->unused_property_fields() - 1;
+ if (unused_property_fields < 0) {
+ unused_property_fields += JSObject::kFieldsAdded;
+ }
+ new_map->set_unused_property_fields(unused_property_fields);
+ return new_map;
+}
+
+
+MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
+ Handle<Name> name,
+ Handle<Object> constant,
+ PropertyAttributes attributes,
+ TransitionFlag flag) {
+ // Ensure the descriptor array does not get too big.
+ if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
+ return MaybeHandle<Map>();
+ }
+
+ // Allocate new instance descriptors with (name, constant) added.
+ ConstantDescriptor new_constant_desc(name, constant, attributes);
+ return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
}
@@ -1815,65 +1891,27 @@
ValueType value_type,
TransitionFlag flag) {
ASSERT(!object->IsJSGlobalProxy());
- ASSERT(DescriptorArray::kNotFound ==
- object->map()->instance_descriptors()->Search(
- *name, object->map()->NumberOfOwnDescriptors()));
- // Normalize the object if the name is an actual name (not the
- // hidden strings) and is not a real identifier.
- // Normalize the object if it will have too many fast properties.
- Isolate* isolate = object->GetIsolate();
- if (!name->IsCacheable(isolate) ||
- object->TooManyFastProperties(store_mode)) {
+ MaybeHandle<Map> maybe_map;
+ if (value->IsJSFunction()) {
+ maybe_map = Map::CopyWithConstant(
+ handle(object->map()), name, value, attributes, flag);
+ } else if (!object->TooManyFastProperties(store_mode)) {
+ Isolate* isolate = object->GetIsolate();
+ Representation representation = value->OptimalRepresentation(value_type);
+ maybe_map = Map::CopyWithField(
+ handle(object->map(), isolate), name,
+ value->OptimalType(isolate, representation),
+ attributes, representation, flag);
+ }
+
+ Handle<Map> new_map;
+ if (!maybe_map.ToHandle(&new_map)) {
NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
- AddSlowProperty(object, name, value, attributes);
return;
}
- // Allocate new instance descriptors with (name, index) added
- if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
- Representation representation = value->OptimalRepresentation(value_type);
-
- // Compute the new index for new field.
- int index = object->map()->NextFreePropertyIndex();
-
- FieldDescriptor new_field_desc(name, index, attributes, representation);
- Handle<Map> new_map = Map::CopyAddDescriptor(
- handle(object->map()), &new_field_desc, flag);
- int unused_property_fields = new_map->unused_property_fields() - 1;
- if (unused_property_fields < 0) {
- unused_property_fields += JSObject::kFieldsAdded;
- }
- new_map->set_unused_property_fields(unused_property_fields);
-
- JSObject::MigrateToMap(object, new_map);
-
- if (representation.IsDouble()) {
- // Nothing more to be done.
- if (value->IsUninitialized()) return;
- HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index));
- box->set_value(value->Number());
- } else {
- object->FastPropertyAtPut(index, *value);
- }
-}
-
-
-void JSObject::AddConstantProperty(Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> constant,
- PropertyAttributes attributes,
- TransitionFlag initial_flag) {
- ASSERT(!object->IsGlobalObject());
- // Don't add transitions to special properties with non-trivial attributes.
- TransitionFlag flag = attributes != NONE ? OMIT_TRANSITION : initial_flag;
-
- // Allocate new instance descriptors with (name, constant) added.
- ConstantDescriptor new_constant_desc(name, constant, attributes);
- Handle<Map> new_map = Map::CopyAddDescriptor(
- handle(object->map()), &new_constant_desc, flag);
-
- JSObject::MigrateToMap(object, new_map);
+ JSObject::MigrateToNewProperty(object, new_map, value);
}
@@ -1941,25 +1979,11 @@
}
if (object->HasFastProperties()) {
- // Ensure the descriptor array does not get too big.
- if (object->map()->NumberOfOwnDescriptors() <= kMaxNumberOfDescriptors) {
- // TODO(verwaest): Support other constants.
- // if (mode == ALLOW_AS_CONSTANT &&
- // !value->IsTheHole() &&
- // !value->IsConsString()) {
- if (value->IsJSFunction()) {
- AddConstantProperty(object, name, value, attributes, transition_flag);
- } else {
- AddFastProperty(object, name, value, attributes, store_mode,
- value_type, transition_flag);
- }
- } else {
- // Normalize the object to prevent very large instance descriptors.
- // This eliminates unwanted N^2 allocation and lookup behavior.
- NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
- AddSlowProperty(object, name, value, attributes);
- }
- } else {
+ AddFastProperty(object, name, value, attributes, store_mode,
+ value_type, transition_flag);
+ }
+
+ if (!object->HasFastProperties()) {
AddSlowProperty(object, name, value, attributes);
}
@@ -2218,7 +2242,7 @@
if (old_details.representation().IsNone()) {
value = handle(Smi::FromInt(0), isolate);
}
- value = NewStorageFor(isolate, value, details.representation());
+ value = Object::NewStorageFor(isolate, value, details.representation());
}
ASSERT(!(details.representation().IsDouble() && value->IsSmi()));
int target_index = new_descriptors->GetFieldIndex(i) - inobject;
@@ -2229,12 +2253,15 @@
for (int i = old_nof; i < new_nof; i++) {
PropertyDetails details = new_descriptors->GetDetails(i);
if (details.type() != FIELD) continue;
+ Handle<Object> value;
if (details.representation().IsDouble()) {
- int target_index = new_descriptors->GetFieldIndex(i) - inobject;
- if (target_index < 0) target_index += total_size;
- Handle<Object> box = isolate->factory()->NewHeapNumber(0);
- array->set(target_index, *box);
+ value = isolate->factory()->NewHeapNumber(0);
+ } else {
+ value = isolate->factory()->uninitialized_value();
}
+ int target_index = new_descriptors->GetFieldIndex(i) - inobject;
+ if (target_index < 0) target_index += total_size;
+ array->set(target_index, *value);
}
// From here on we cannot fail and we shouldn't GC anymore.
@@ -2277,9 +2304,11 @@
void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object,
int modify_index,
Representation new_representation,
+ Handle<HeapType> new_field_type,
StoreMode store_mode) {
Handle<Map> new_map = Map::GeneralizeRepresentation(
- handle(object->map()), modify_index, new_representation, store_mode);
+ handle(object->map()), modify_index, new_representation,
+ new_field_type, store_mode);
if (object->map() == *new_map) return;
return MigrateToMap(object, new_map);
}
@@ -2300,16 +2329,22 @@
StoreMode store_mode,
PropertyAttributes attributes,
const char* reason) {
+ Isolate* isolate = map->GetIsolate();
Handle<Map> new_map = Copy(map);
DescriptorArray* descriptors = new_map->instance_descriptors();
- descriptors->InitializeRepresentations(Representation::Tagged());
+ int length = descriptors->number_of_descriptors();
+ for (int i = 0; i < length; i++) {
+ descriptors->SetRepresentation(i, Representation::Tagged());
+ if (descriptors->GetDetails(i).type() == FIELD) {
+ descriptors->SetValue(i, HeapType::Any());
+ }
+ }
// Unless the instance is being migrated, ensure that modify_index is a field.
PropertyDetails details = descriptors->GetDetails(modify_index);
if (store_mode == FORCE_FIELD && details.type() != FIELD) {
- FieldDescriptor d(handle(descriptors->GetKey(modify_index),
- map->GetIsolate()),
+ FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
new_map->NumberOfFields(),
attributes,
Representation::Tagged());
@@ -2322,11 +2357,15 @@
}
if (FLAG_trace_generalization) {
+ HeapType* field_type = (details.type() == FIELD)
+ ? map->instance_descriptors()->GetFieldType(modify_index)
+ : NULL;
map->PrintGeneralization(stdout, reason, modify_index,
new_map->NumberOfOwnDescriptors(),
new_map->NumberOfOwnDescriptors(),
details.type() == CONSTANT && store_mode == FORCE_FIELD,
- Representation::Tagged(), Representation::Tagged());
+ details.representation(), Representation::Tagged(),
+ field_type, HeapType::Any());
}
return new_map;
}
@@ -2391,6 +2430,8 @@
Map* Map::FindUpdatedMap(int verbatim,
int length,
DescriptorArray* descriptors) {
+ DisallowHeapAllocation no_allocation;
+
// This can only be called on roots of transition trees.
ASSERT(GetBackPointer()->IsUndefined());
@@ -2425,6 +2466,8 @@
Map* Map::FindLastMatchMap(int verbatim,
int length,
DescriptorArray* descriptors) {
+ DisallowHeapAllocation no_allocation;
+
// This can only be called on roots of transition trees.
ASSERT(GetBackPointer()->IsUndefined());
@@ -2440,13 +2483,17 @@
Map* next = transitions->GetTarget(transition);
DescriptorArray* next_descriptors = next->instance_descriptors();
- if (next_descriptors->GetValue(i) != descriptors->GetValue(i)) break;
-
PropertyDetails details = descriptors->GetDetails(i);
PropertyDetails next_details = next_descriptors->GetDetails(i);
if (details.type() != next_details.type()) break;
if (details.attributes() != next_details.attributes()) break;
if (!details.representation().Equals(next_details.representation())) break;
+ if (next_details.type() == FIELD) {
+ if (!descriptors->GetFieldType(i)->NowIs(
+ next_descriptors->GetFieldType(i))) break;
+ } else {
+ if (descriptors->GetValue(i) != next_descriptors->GetValue(i)) break;
+ }
current = next;
}
@@ -2454,6 +2501,97 @@
}
+Map* Map::FindFieldOwner(int descriptor) {
+ DisallowHeapAllocation no_allocation;
+ ASSERT_EQ(FIELD, instance_descriptors()->GetDetails(descriptor).type());
+ Map* result = this;
+ while (true) {
+ Object* back = result->GetBackPointer();
+ if (back->IsUndefined()) break;
+ Map* parent = Map::cast(back);
+ if (parent->NumberOfOwnDescriptors() <= descriptor) break;
+ result = parent;
+ }
+ return result;
+}
+
+
+void Map::UpdateDescriptor(int descriptor_number, Descriptor* desc) {
+ DisallowHeapAllocation no_allocation;
+ if (HasTransitionArray()) {
+ TransitionArray* transitions = this->transitions();
+ for (int i = 0; i < transitions->number_of_transitions(); ++i) {
+ transitions->GetTarget(i)->UpdateDescriptor(descriptor_number, desc);
+ }
+ }
+ instance_descriptors()->Replace(descriptor_number, desc);;
+}
+
+
+// static
+Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
+ Handle<HeapType> type2,
+ Isolate* isolate) {
+ static const int kMaxClassesPerFieldType = 5;
+ if (type1->NowIs(type2)) return type2;
+ if (type2->NowIs(type1)) return type1;
+ if (type1->NowStable() && type2->NowStable()) {
+ Handle<HeapType> type = HeapType::Union(type1, type2, isolate);
+ if (type->NumClasses() <= kMaxClassesPerFieldType) {
+ ASSERT(type->NowStable());
+ ASSERT(type1->NowIs(type));
+ ASSERT(type2->NowIs(type));
+ return type;
+ }
+ }
+ return HeapType::Any(isolate);
+}
+
+
+// static
+void Map::GeneralizeFieldType(Handle<Map> map,
+ int modify_index,
+ Handle<HeapType> new_field_type) {
+ Isolate* isolate = map->GetIsolate();
+ Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
+ Handle<DescriptorArray> descriptors(
+ field_owner->instance_descriptors(), isolate);
+
+ // Check if we actually need to generalize the field type at all.
+ Handle<HeapType> old_field_type(
+ descriptors->GetFieldType(modify_index), isolate);
+ if (new_field_type->NowIs(old_field_type)) {
+ ASSERT(Map::GeneralizeFieldType(old_field_type,
+ new_field_type,
+ isolate)->NowIs(old_field_type));
+ return;
+ }
+
+ // Determine the generalized new field type.
+ new_field_type = Map::GeneralizeFieldType(
+ old_field_type, new_field_type, isolate);
+
+ PropertyDetails details = descriptors->GetDetails(modify_index);
+ FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
+ descriptors->GetFieldIndex(modify_index),
+ new_field_type,
+ details.attributes(),
+ details.representation());
+ field_owner->UpdateDescriptor(modify_index, &d);
+ field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
+ isolate, DependentCode::kFieldTypeGroup);
+
+ if (FLAG_trace_generalization) {
+ map->PrintGeneralization(
+ stdout, "field type generalization",
+ modify_index, map->NumberOfOwnDescriptors(),
+ map->NumberOfOwnDescriptors(), false,
+ details.representation(), details.representation(),
+ *old_field_type, *new_field_type);
+ }
+}
+
+
// Generalize the representation of the descriptor at |modify_index|.
// This method rewrites the transition tree to reflect the new change. To avoid
// high degrees over polymorphism, and to stabilize quickly, on every rewrite
@@ -2475,6 +2613,7 @@
Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
int modify_index,
Representation new_representation,
+ Handle<HeapType> new_field_type,
StoreMode store_mode) {
Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
@@ -2487,11 +2626,28 @@
if (old_representation.IsNone() &&
!new_representation.IsNone() &&
!new_representation.IsDouble()) {
+ ASSERT(old_details.type() == FIELD);
+ ASSERT(old_descriptors->GetFieldType(modify_index)->NowIs(
+ HeapType::None()));
+ if (FLAG_trace_generalization) {
+ old_map->PrintGeneralization(
+ stdout, "uninitialized field",
+ modify_index, old_map->NumberOfOwnDescriptors(),
+ old_map->NumberOfOwnDescriptors(), false,
+ old_representation, new_representation,
+ old_descriptors->GetFieldType(modify_index), *new_field_type);
+ }
old_descriptors->SetRepresentation(modify_index, new_representation);
+ old_descriptors->SetValue(modify_index, *new_field_type);
return old_map;
}
- int descriptors = old_map->NumberOfOwnDescriptors();
+ if (new_representation.Equals(old_representation) &&
+ old_details.type() == FIELD) {
+ Map::GeneralizeFieldType(old_map, modify_index, new_field_type);
+ return old_map;
+ }
+
Handle<Map> root_map(old_map->FindRootMap());
// Check the state of the root map.
@@ -2507,6 +2663,7 @@
old_details.attributes(), "root modification");
}
+ int descriptors = old_map->NumberOfOwnDescriptors();
Map* raw_updated = root_map->FindUpdatedMap(
verbatim, descriptors, *old_descriptors);
if (raw_updated == NULL) {
@@ -2536,6 +2693,7 @@
ASSERT(store_mode == ALLOW_AS_CONSTANT ||
new_descriptors->GetDetails(modify_index).type() == FIELD);
+ Isolate* isolate = new_descriptors->GetIsolate();
old_representation =
new_descriptors->GetDetails(modify_index).representation();
Representation updated_representation =
@@ -2543,6 +2701,13 @@
if (!updated_representation.Equals(old_representation)) {
new_descriptors->SetRepresentation(modify_index, updated_representation);
}
+ if (new_descriptors->GetDetails(modify_index).type() == FIELD) {
+ Handle<HeapType> field_type(
+ new_descriptors->GetFieldType(modify_index), isolate);
+ new_field_type = Map::GeneralizeFieldType(
+ field_type, new_field_type, isolate);
+ new_descriptors->SetValue(modify_index, *new_field_type);
+ }
Handle<Map> split_map(root_map->FindLastMatchMap(
verbatim, descriptors, *new_descriptors));
@@ -2557,11 +2722,21 @@
old_descriptors->GetKey(descriptor), *new_descriptors);
if (FLAG_trace_generalization) {
+ PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
+ PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
+ Handle<HeapType> old_field_type = (old_details.type() == FIELD)
+ ? handle(old_descriptors->GetFieldType(modify_index), isolate)
+ : HeapType::Constant(handle(old_descriptors->GetValue(modify_index),
+ isolate), isolate);
+ Handle<HeapType> new_field_type = (new_details.type() == FIELD)
+ ? handle(new_descriptors->GetFieldType(modify_index), isolate)
+ : HeapType::Constant(handle(new_descriptors->GetValue(modify_index),
+ isolate), isolate);
old_map->PrintGeneralization(
stdout, "", modify_index, descriptor, descriptors,
- old_descriptors->GetDetails(modify_index).type() == CONSTANT &&
- store_mode == FORCE_FIELD,
- old_representation, updated_representation);
+ old_details.type() == CONSTANT && store_mode == FORCE_FIELD,
+ old_details.representation(), new_details.representation(),
+ *old_field_type, *new_field_type);
}
// Add missing transitions.
@@ -2577,13 +2752,13 @@
// Generalize the representation of all FIELD descriptors.
Handle<Map> Map::GeneralizeAllFieldRepresentations(
- Handle<Map> map,
- Representation new_representation) {
+ Handle<Map> map) {
Handle<DescriptorArray> descriptors(map->instance_descriptors());
- for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
- PropertyDetails details = descriptors->GetDetails(i);
- if (details.type() == FIELD) {
- map = GeneralizeRepresentation(map, i, new_representation, FORCE_FIELD);
+ for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
+ if (descriptors->GetDetails(i).type() == FIELD) {
+ map = GeneralizeRepresentation(map, i, Representation::Tagged(),
+ HeapType::Any(map->GetIsolate()),
+ FORCE_FIELD);
}
}
return map;
@@ -2725,8 +2900,7 @@
if (call_fun == NULL) return value;
Handle<String> key = Handle<String>::cast(name);
LOG(isolate, ApiNamedPropertyAccess("store", *object, *name));
- PropertyCallbackArguments args(
- isolate, data->data(), *object, JSObject::cast(*holder));
+ PropertyCallbackArguments args(isolate, data->data(), *object, *holder);
args.Call(call_fun,
v8::Utils::ToLocal(key),
v8::Utils::ToLocal(value));
@@ -3722,7 +3896,9 @@
// transition that matches the object. This achieves what is needed.
Handle<Map> original_map(object->map());
GeneralizeFieldRepresentation(
- object, 0, Representation::None(), ALLOW_AS_CONSTANT);
+ object, 0, Representation::None(),
+ HeapType::None(object->GetIsolate()),
+ ALLOW_AS_CONSTANT);
object->map()->set_migration_target(true);
if (FLAG_trace_migration) {
object->PrintInstanceMigration(stdout, *original_map, object->map());
@@ -3751,7 +3927,7 @@
Handle<Map> transition_map(lookup->GetTransitionTarget());
int descriptor = transition_map->LastAdded();
- DescriptorArray* descriptors = transition_map->instance_descriptors();
+ Handle<DescriptorArray> descriptors(transition_map->instance_descriptors());
PropertyDetails details = descriptors->GetDetails(descriptor);
if (details.type() == CALLBACKS || attributes != details.attributes()) {
@@ -3768,58 +3944,61 @@
// Keep the target CONSTANT if the same value is stored.
// TODO(verwaest): Also support keeping the placeholder
// (value->IsUninitialized) as constant.
- if (!lookup->CanHoldValue(value) ||
- (details.type() == CONSTANT &&
- descriptors->GetValue(descriptor) != *value)) {
- transition_map = Map::GeneralizeRepresentation(transition_map,
- descriptor, value->OptimalRepresentation(), FORCE_FIELD);
+ if (!lookup->CanHoldValue(value)) {
+ Representation field_representation = value->OptimalRepresentation();
+ Handle<HeapType> field_type = value->OptimalType(
+ lookup->isolate(), field_representation);
+ transition_map = Map::GeneralizeRepresentation(
+ transition_map, descriptor,
+ field_representation, field_type, FORCE_FIELD);
}
- JSObject::MigrateToMap(object, transition_map);
+ JSObject::MigrateToNewProperty(object, transition_map, value);
+ return value;
+}
- // Reload.
- descriptors = transition_map->instance_descriptors();
- details = descriptors->GetDetails(descriptor);
- if (details.type() != FIELD) return value;
+void JSObject::MigrateToNewProperty(Handle<JSObject> object,
+ Handle<Map> map,
+ Handle<Object> value) {
+ JSObject::MigrateToMap(object, map);
+ if (map->GetLastDescriptorDetails().type() != FIELD) return;
+ object->WriteToField(map->LastAdded(), *value);
+}
- int field_index = descriptors->GetFieldIndex(descriptor);
+
+void JSObject::WriteToField(int descriptor, Object* value) {
+ DisallowHeapAllocation no_gc;
+
+ DescriptorArray* desc = map()->instance_descriptors();
+ PropertyDetails details = desc->GetDetails(descriptor);
+
+ ASSERT(details.type() == FIELD);
+
+ int field_index = desc->GetFieldIndex(descriptor);
if (details.representation().IsDouble()) {
// Nothing more to be done.
- if (value->IsUninitialized()) return value;
- HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(field_index));
+ if (value->IsUninitialized()) return;
+ HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(field_index));
box->set_value(value->Number());
} else {
- object->FastPropertyAtPut(field_index, *value);
+ FastPropertyAtPut(field_index, value);
}
-
- return value;
}
static void SetPropertyToField(LookupResult* lookup,
Handle<Object> value) {
- Representation representation = lookup->representation();
- if (!lookup->CanHoldValue(value) ||
- lookup->type() == CONSTANT) {
+ if (lookup->type() == CONSTANT || !lookup->CanHoldValue(value)) {
+ Representation field_representation = value->OptimalRepresentation();
+ Handle<HeapType> field_type = value->OptimalType(
+ lookup->isolate(), field_representation);
JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()),
lookup->GetDescriptorIndex(),
- value->OptimalRepresentation(),
+ field_representation, field_type,
FORCE_FIELD);
- DescriptorArray* desc = lookup->holder()->map()->instance_descriptors();
- int descriptor = lookup->GetDescriptorIndex();
- representation = desc->GetDetails(descriptor).representation();
}
-
- if (representation.IsDouble()) {
- HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt(
- lookup->GetFieldIndex().field_index()));
- storage->set_value(value->Number());
- return;
- }
-
- lookup->holder()->FastPropertyAtPut(
- lookup->GetFieldIndex().field_index(), *value);
+ lookup->holder()->WriteToField(lookup->GetDescriptorIndex(), *value);
}
@@ -3840,7 +4019,8 @@
int descriptor_index = lookup->GetDescriptorIndex();
if (lookup->GetAttributes() == attributes) {
JSObject::GeneralizeFieldRepresentation(
- object, descriptor_index, Representation::Tagged(), FORCE_FIELD);
+ object, descriptor_index, Representation::Tagged(),
+ HeapType::Any(lookup->isolate()), FORCE_FIELD);
} else {
Handle<Map> old_map(object->map());
Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map,
@@ -3848,9 +4028,7 @@
JSObject::MigrateToMap(object, new_map);
}
- DescriptorArray* descriptors = object->map()->instance_descriptors();
- int index = descriptors->GetDetails(descriptor_index).field_index();
- object->FastPropertyAtPut(index, *value);
+ object->WriteToField(descriptor_index, *value);
}
@@ -5045,9 +5223,7 @@
int sorted_index = descriptors->GetSortedKeyIndex(0);
if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string()
&& sorted_index < object->map()->NumberOfOwnDescriptors()) {
- ASSERT(descriptors->GetType(sorted_index) == FIELD);
- object->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
- *value);
+ object->WriteToField(sorted_index, *value);
return object;
}
}
@@ -5080,8 +5256,8 @@
}
-Handle<Object> JSObject::DeletePropertyWithInterceptor(Handle<JSObject> object,
- Handle<Name> name) {
+MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor(
+ Handle<JSObject> object, Handle<Name> name) {
Isolate* isolate = object->GetIsolate();
// TODO(rossberg): Support symbols in the API.
@@ -5097,7 +5273,7 @@
isolate, interceptor->data(), *object, *object);
v8::Handle<v8::Boolean> result =
args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name)));
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
if (!result.IsEmpty()) {
ASSERT(result->IsBoolean());
Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
@@ -5108,7 +5284,6 @@
}
Handle<Object> result =
DeletePropertyPostInterceptor(object, name, NORMAL_DELETION);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
return result;
}
@@ -5132,7 +5307,7 @@
PropertyCallbackArguments args(
isolate, interceptor->data(), *object, *object);
v8::Handle<v8::Boolean> result = args.Call(deleter, index);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
if (!result.IsEmpty()) {
ASSERT(result->IsBoolean());
Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
@@ -5156,7 +5331,7 @@
if (object->IsAccessCheckNeeded() &&
!isolate->MayIndexedAccess(object, index, v8::ACCESS_DELETE)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return factory->false_value();
}
@@ -5225,7 +5400,7 @@
if (object->IsAccessCheckNeeded() &&
!isolate->MayNamedAccess(object, name, v8::ACCESS_DELETE)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->false_value();
}
@@ -5272,7 +5447,10 @@
if (mode == FORCE_DELETION) {
result = DeletePropertyPostInterceptor(object, name, mode);
} else {
- result = DeletePropertyWithInterceptor(object, name);
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result,
+ DeletePropertyWithInterceptor(object, name),
+ Object);
}
} else {
// Normalize object if needed.
@@ -5447,7 +5625,7 @@
}
-Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
+MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
Isolate* isolate = object->GetIsolate();
if (!object->map()->is_extensible()) return object;
@@ -5456,7 +5634,7 @@
!isolate->MayNamedAccess(
object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->false_value();
}
@@ -5474,8 +5652,7 @@
isolate->factory()->NewTypeError(
"cant_prevent_ext_external_array_elements",
HandleVector(&object, 1));
- isolate->Throw(*error);
- return Handle<Object>();
+ return isolate->Throw<Object>(error);
}
// If there are fast elements we normalize.
@@ -5594,16 +5771,7 @@
JSObject::MigrateToMap(object, transition_map);
} else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
// Create a new descriptor array with fully-frozen properties
- int num_descriptors = old_map->NumberOfOwnDescriptors();
- Handle<DescriptorArray> new_descriptors =
- DescriptorArray::CopyUpToAddAttributes(
- handle(old_map->instance_descriptors()), num_descriptors, FROZEN);
- Handle<Map> new_map = Map::CopyReplaceDescriptors(
- old_map, new_descriptors, INSERT_TRANSITION,
- isolate->factory()->frozen_symbol());
- new_map->freeze();
- new_map->set_is_extensible(false);
- new_map->set_elements_kind(DICTIONARY_ELEMENTS);
+ Handle<Map> new_map = Map::CopyForFreeze(old_map);
JSObject::MigrateToMap(object, new_map);
} else {
// Slow path: need to normalize properties for safety
@@ -5648,7 +5816,7 @@
if (transition_index != TransitionArray::kNotFound) {
new_map = handle(old_map->GetTransition(transition_index), isolate);
ASSERT(new_map->is_observed());
- } else if (old_map->CanHaveMoreTransitions()) {
+ } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
new_map = Map::CopyForObserved(old_map);
} else {
new_map = Map::Copy(old_map);
@@ -5658,10 +5826,22 @@
}
+Handle<JSObject> JSObject::Copy(Handle<JSObject> object,
+ Handle<AllocationSite> site) {
+ Isolate* isolate = object->GetIsolate();
+ CALL_HEAP_FUNCTION(isolate,
+ isolate->heap()->CopyJSObject(
+ *object,
+ site.is_null() ? NULL : *site),
+ JSObject);
+}
+
+
Handle<JSObject> JSObject::Copy(Handle<JSObject> object) {
Isolate* isolate = object->GetIsolate();
CALL_HEAP_FUNCTION(isolate,
- isolate->heap()->CopyJSObject(*object), JSObject);
+ isolate->heap()->CopyJSObject(*object, NULL),
+ JSObject);
}
@@ -5669,8 +5849,8 @@
Representation representation,
int index) {
Isolate* isolate = object->GetIsolate();
- CALL_HEAP_FUNCTION(isolate,
- object->FastPropertyAt(representation, index), Object);
+ Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
+ return Object::NewStorageFor(isolate, raw_value, representation);
}
@@ -5683,13 +5863,14 @@
copying_(copying),
hints_(hints) {}
- Handle<JSObject> StructureWalk(Handle<JSObject> object);
+ MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
protected:
- inline Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object,
- Handle<JSObject> value) {
+ MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
+ Handle<JSObject> object,
+ Handle<JSObject> value) {
Handle<AllocationSite> current_site = site_context()->EnterNewScope();
- Handle<JSObject> copy_of_value = StructureWalk(value);
+ MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
site_context()->ExitScope(current_site, value);
return copy_of_value;
}
@@ -5707,7 +5888,7 @@
template <class ContextObject>
-Handle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
+MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
Handle<JSObject> object) {
Isolate* isolate = this->isolate();
bool copying = this->copying();
@@ -5718,7 +5899,7 @@
if (check.HasOverflowed()) {
isolate->StackOverflow();
- return Handle<JSObject>::null();
+ return MaybeHandle<JSObject>();
}
}
@@ -5732,14 +5913,7 @@
if (site_context()->ShouldCreateMemento(object)) {
site_to_pass = site_context()->current();
}
- CALL_AND_RETRY_OR_DIE(isolate,
- isolate->heap()->CopyJSObject(*object,
- site_to_pass.is_null() ? NULL : *site_to_pass),
- { copy = Handle<JSObject>(JSObject::cast(__object__),
- isolate);
- break;
- },
- return Handle<JSObject>());
+ copy = JSObject::Copy(object, site_to_pass);
} else {
copy = object;
}
@@ -5766,11 +5940,13 @@
int index = descriptors->GetFieldIndex(i);
Handle<Object> value(object->RawFastPropertyAt(index), isolate);
if (value->IsJSObject()) {
- value = VisitElementOrProperty(copy, Handle<JSObject>::cast(value));
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<JSObject>());
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, value,
+ VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
+ JSObject);
} else {
Representation representation = details.representation();
- value = NewStorageFor(isolate, value, representation);
+ value = Object::NewStorageFor(isolate, value, representation);
}
if (copying) {
copy->FastPropertyAtPut(index, *value);
@@ -5792,9 +5968,11 @@
Handle<Object> value =
Object::GetProperty(copy, key_string).ToHandleChecked();
if (value->IsJSObject()) {
- Handle<JSObject> result = VisitElementOrProperty(
- copy, Handle<JSObject>::cast(value));
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
+ Handle<JSObject> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result,
+ VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
+ JSObject);
if (copying) {
// Creating object copy for literals. No strict mode needed.
JSObject::SetProperty(
@@ -5826,9 +6004,11 @@
value->IsTheHole() ||
(IsFastObjectElementsKind(copy->GetElementsKind())));
if (value->IsJSObject()) {
- Handle<JSObject> result = VisitElementOrProperty(
- copy, Handle<JSObject>::cast(value));
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
+ Handle<JSObject> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result,
+ VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
+ JSObject);
if (copying) {
elements->set(i, *result);
}
@@ -5846,9 +6026,11 @@
if (element_dictionary->IsKey(k)) {
Handle<Object> value(element_dictionary->ValueAt(i), isolate);
if (value->IsJSObject()) {
- Handle<JSObject> result = VisitElementOrProperty(
- copy, Handle<JSObject>::cast(value));
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
+ Handle<JSObject> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result,
+ VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
+ JSObject);
if (copying) {
element_dictionary->ValueAtPut(i, *result);
}
@@ -5880,23 +6062,26 @@
}
-Handle<JSObject> JSObject::DeepWalk(
+MaybeHandle<JSObject> JSObject::DeepWalk(
Handle<JSObject> object,
AllocationSiteCreationContext* site_context) {
JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
kNoHints);
- Handle<JSObject> result = v.StructureWalk(object);
- ASSERT(result.is_null() || result.is_identical_to(object));
+ MaybeHandle<JSObject> result = v.StructureWalk(object);
+ Handle<JSObject> for_assert;
+ ASSERT(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
return result;
}
-Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object,
- AllocationSiteUsageContext* site_context,
- DeepCopyHints hints) {
+MaybeHandle<JSObject> JSObject::DeepCopy(
+ Handle<JSObject> object,
+ AllocationSiteUsageContext* site_context,
+ DeepCopyHints hints) {
JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
- Handle<JSObject> copy = v.StructureWalk(object);
- ASSERT(!copy.is_identical_to(object));
+ MaybeHandle<JSObject> copy = v.StructureWalk(object);
+ Handle<JSObject> for_assert;
+ ASSERT(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
return copy;
}
@@ -6081,6 +6266,247 @@
}
+static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
+ int len = array->length();
+ for (int i = 0; i < len; i++) {
+ Object* e = array->get(i);
+ if (!(e->IsString() || e->IsNumber())) return false;
+ }
+ return true;
+}
+
+
+static Handle<FixedArray> ReduceFixedArrayTo(
+ Handle<FixedArray> array, int length) {
+ ASSERT(array->length() >= length);
+ if (array->length() == length) return array;
+
+ Handle<FixedArray> new_array =
+ array->GetIsolate()->factory()->NewFixedArray(length);
+ for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
+ return new_array;
+}
+
+
+static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
+ bool cache_result) {
+ Isolate* isolate = object->GetIsolate();
+ if (object->HasFastProperties()) {
+ int own_property_count = object->map()->EnumLength();
+ // If the enum length of the given map is set to kInvalidEnumCache, this
+ // means that the map itself has never used the present enum cache. The
+ // first step to using the cache is to set the enum length of the map by
+ // counting the number of own descriptors that are not DONT_ENUM or
+ // SYMBOLIC.
+ if (own_property_count == kInvalidEnumCacheSentinel) {
+ own_property_count = object->map()->NumberOfDescribedProperties(
+ OWN_DESCRIPTORS, DONT_SHOW);
+ } else {
+ ASSERT(own_property_count == object->map()->NumberOfDescribedProperties(
+ OWN_DESCRIPTORS, DONT_SHOW));
+ }
+
+ if (object->map()->instance_descriptors()->HasEnumCache()) {
+ DescriptorArray* desc = object->map()->instance_descriptors();
+ Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
+
+ // In case the number of properties required in the enum are actually
+ // present, we can reuse the enum cache. Otherwise, this means that the
+ // enum cache was generated for a previous (smaller) version of the
+ // Descriptor Array. In that case we regenerate the enum cache.
+ if (own_property_count <= keys->length()) {
+ if (cache_result) object->map()->SetEnumLength(own_property_count);
+ isolate->counters()->enum_cache_hits()->Increment();
+ return ReduceFixedArrayTo(keys, own_property_count);
+ }
+ }
+
+ Handle<Map> map(object->map());
+
+ if (map->instance_descriptors()->IsEmpty()) {
+ isolate->counters()->enum_cache_hits()->Increment();
+ if (cache_result) map->SetEnumLength(0);
+ return isolate->factory()->empty_fixed_array();
+ }
+
+ isolate->counters()->enum_cache_misses()->Increment();
+
+ Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
+ own_property_count);
+ Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
+ own_property_count);
+
+ Handle<DescriptorArray> descs =
+ Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
+
+ int size = map->NumberOfOwnDescriptors();
+ int index = 0;
+
+ for (int i = 0; i < size; i++) {
+ PropertyDetails details = descs->GetDetails(i);
+ Object* key = descs->GetKey(i);
+ if (!(details.IsDontEnum() || key->IsSymbol())) {
+ storage->set(index, key);
+ if (!indices.is_null()) {
+ if (details.type() != FIELD) {
+ indices = Handle<FixedArray>();
+ } else {
+ int field_index = descs->GetFieldIndex(i);
+ if (field_index >= map->inobject_properties()) {
+ field_index = -(field_index - map->inobject_properties() + 1);
+ }
+ field_index = field_index << 1;
+ if (details.representation().IsDouble()) {
+ field_index |= 1;
+ }
+ indices->set(index, Smi::FromInt(field_index));
+ }
+ }
+ index++;
+ }
+ }
+ ASSERT(index == storage->length());
+
+ Handle<FixedArray> bridge_storage =
+ isolate->factory()->NewFixedArray(
+ DescriptorArray::kEnumCacheBridgeLength);
+ DescriptorArray* desc = object->map()->instance_descriptors();
+ desc->SetEnumCache(*bridge_storage,
+ *storage,
+ indices.is_null() ? Object::cast(Smi::FromInt(0))
+ : Object::cast(*indices));
+ if (cache_result) {
+ object->map()->SetEnumLength(own_property_count);
+ }
+ return storage;
+ } else {
+ Handle<NameDictionary> dictionary(object->property_dictionary());
+ int length = dictionary->NumberOfEnumElements();
+ if (length == 0) {
+ return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
+ }
+ Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
+ dictionary->CopyEnumKeysTo(*storage);
+ return storage;
+ }
+}
+
+
+MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
+ KeyCollectionType type) {
+ USE(ContainsOnlyValidKeys);
+ Isolate* isolate = object->GetIsolate();
+ Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
+ Handle<JSObject> arguments_boilerplate = Handle<JSObject>(
+ isolate->context()->native_context()->sloppy_arguments_boilerplate(),
+ isolate);
+ Handle<JSFunction> arguments_function = Handle<JSFunction>(
+ JSFunction::cast(arguments_boilerplate->map()->constructor()),
+ isolate);
+
+ // Only collect keys if access is permitted.
+ for (Handle<Object> p = object;
+ *p != isolate->heap()->null_value();
+ p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
+ if (p->IsJSProxy()) {
+ Handle<JSProxy> proxy(JSProxy::cast(*p), isolate);
+ Handle<Object> args[] = { proxy };
+ Handle<Object> names;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, names,
+ Execution::Call(isolate,
+ isolate->proxy_enumerate(),
+ object,
+ ARRAY_SIZE(args),
+ args),
+ FixedArray);
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, content,
+ FixedArray::AddKeysFromJSArray(
+ content, Handle<JSArray>::cast(names)),
+ FixedArray);
+ break;
+ }
+
+ Handle<JSObject> current(JSObject::cast(*p), isolate);
+
+ // Check access rights if required.
+ if (current->IsAccessCheckNeeded() &&
+ !isolate->MayNamedAccess(
+ current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
+ isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
+ break;
+ }
+
+ // Compute the element keys.
+ Handle<FixedArray> element_keys =
+ isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
+ current->GetEnumElementKeys(*element_keys);
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, content,
+ FixedArray::UnionOfKeys(content, element_keys),
+ FixedArray);
+ ASSERT(ContainsOnlyValidKeys(content));
+
+ // Add the element keys from the interceptor.
+ if (current->HasIndexedInterceptor()) {
+ Handle<JSArray> result;
+ if (JSObject::GetKeysForIndexedInterceptor(
+ current, object).ToHandle(&result)) {
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, content,
+ FixedArray::AddKeysFromJSArray(content, result),
+ FixedArray);
+ }
+ ASSERT(ContainsOnlyValidKeys(content));
+ }
+
+ // We can cache the computed property keys if access checks are
+ // not needed and no interceptors are involved.
+ //
+ // We do not use the cache if the object has elements and
+ // therefore it does not make sense to cache the property names
+ // for arguments objects. Arguments objects will always have
+ // elements.
+ // Wrapped strings have elements, but don't have an elements
+ // array or dictionary. So the fast inline test for whether to
+ // use the cache says yes, so we should not create a cache.
+ bool cache_enum_keys =
+ ((current->map()->constructor() != *arguments_function) &&
+ !current->IsJSValue() &&
+ !current->IsAccessCheckNeeded() &&
+ !current->HasNamedInterceptor() &&
+ !current->HasIndexedInterceptor());
+ // Compute the property keys and cache them if possible.
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, content,
+ FixedArray::UnionOfKeys(
+ content, GetEnumPropertyKeys(current, cache_enum_keys)),
+ FixedArray);
+ ASSERT(ContainsOnlyValidKeys(content));
+
+ // Add the property keys from the interceptor.
+ if (current->HasNamedInterceptor()) {
+ Handle<JSArray> result;
+ if (JSObject::GetKeysForNamedInterceptor(
+ current, object).ToHandle(&result)) {
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, content,
+ FixedArray::AddKeysFromJSArray(content, result),
+ FixedArray);
+ }
+ ASSERT(ContainsOnlyValidKeys(content));
+ }
+
+ // If we only want local properties we bail out after the first
+ // iteration.
+ if (type == LOCAL_ONLY) break;
+ }
+ return content;
+}
+
+
// Try to update an accessor in an elements dictionary. Return true if the
// update succeeded, and false otherwise.
static bool UpdateGetterSetterInDictionary(
@@ -6447,15 +6873,6 @@
}
-static Handle<Map> CopyInsertDescriptor(Handle<Map> map,
- Handle<Name> name,
- Handle<AccessorPair> accessors,
- PropertyAttributes attributes) {
- CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
- return Map::CopyInsertDescriptor(map, &new_accessors_desc, INSERT_TRANSITION);
-}
-
-
bool JSObject::DefineFastAccessor(Handle<JSObject> object,
Handle<Name> name,
AccessorComponent component,
@@ -6520,15 +6937,18 @@
? AccessorPair::Copy(Handle<AccessorPair>(source_accessors))
: isolate->factory()->NewAccessorPair();
accessors->set(component, *accessor);
- Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()),
- name, accessors, attributes);
+
+ CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
+ Handle<Map> new_map = Map::CopyInsertDescriptor(
+ handle(object->map()), &new_accessors_desc, INSERT_TRANSITION);
+
JSObject::MigrateToMap(object, new_map);
return true;
}
-Handle<Object> JSObject::SetAccessor(Handle<JSObject> object,
- Handle<AccessorInfo> info) {
+MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
+ Handle<AccessorInfo> info) {
Isolate* isolate = object->GetIsolate();
Factory* factory = isolate->factory();
Handle<Name> name(Name::cast(info->name()));
@@ -6537,7 +6957,7 @@
if (object->IsAccessCheckNeeded() &&
!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return factory->undefined_value();
}
@@ -6610,9 +7030,9 @@
}
-Handle<Object> JSObject::GetAccessor(Handle<JSObject> object,
- Handle<Name> name,
- AccessorComponent component) {
+MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
+ Handle<Name> name,
+ AccessorComponent component) {
Isolate* isolate = object->GetIsolate();
// Make sure that the top context does not change when doing callbacks or
@@ -6623,7 +7043,7 @@
if (object->IsAccessCheckNeeded() &&
!isolate->MayNamedAccess(object, name, v8::ACCESS_HAS)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->undefined_value();
}
@@ -6806,16 +7226,7 @@
Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
Handle<DescriptorArray> descriptors,
TransitionFlag flag,
- SimpleTransitionFlag simple_flag) {
- return CopyReplaceDescriptors(
- map, descriptors, flag, Handle<Name>::null(), simple_flag);
-}
-
-
-Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
- Handle<DescriptorArray> descriptors,
- TransitionFlag flag,
- Handle<Name> name,
+ MaybeHandle<Name> maybe_name,
SimpleTransitionFlag simple_flag) {
ASSERT(descriptors->IsSortedNoDuplicates());
@@ -6823,12 +7234,20 @@
result->InitializeDescriptors(*descriptors);
if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) {
+ Handle<Name> name;
+ CHECK(maybe_name.ToHandle(&name));
Handle<TransitionArray> transitions = TransitionArray::CopyInsert(
map, name, result, simple_flag);
map->set_transitions(*transitions);
result->SetBackPointer(*map);
} else {
- descriptors->InitializeRepresentations(Representation::Tagged());
+ int length = descriptors->number_of_descriptors();
+ for (int i = 0; i < length; i++) {
+ descriptors->SetRepresentation(i, Representation::Tagged());
+ if (descriptors->GetDetails(i).type() == FIELD) {
+ descriptors->SetValue(i, HeapType::Any());
+ }
+ }
}
return result;
@@ -6953,7 +7372,8 @@
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
Handle<DescriptorArray> new_descriptors =
DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
- return CopyReplaceDescriptors(map, new_descriptors, OMIT_TRANSITION);
+ return CopyReplaceDescriptors(
+ map, new_descriptors, OMIT_TRANSITION, MaybeHandle<Name>());
}
@@ -6986,6 +7406,20 @@
}
+Handle<Map> Map::CopyForFreeze(Handle<Map> map) {
+ int num_descriptors = map->NumberOfOwnDescriptors();
+ Isolate* isolate = map->GetIsolate();
+ Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
+ handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN);
+ Handle<Map> new_map = Map::CopyReplaceDescriptors(
+ map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol());
+ new_map->freeze();
+ new_map->set_is_extensible(false);
+ new_map->set_elements_kind(DICTIONARY_ELEMENTS);
+ return new_map;
+}
+
+
Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
Descriptor* descriptor,
TransitionFlag flag) {
@@ -7106,23 +7540,16 @@
Handle<Name> name,
Handle<Code> code) {
Isolate* isolate = map->GetIsolate();
- CALL_HEAP_FUNCTION_VOID(isolate,
- map->UpdateCodeCache(*name, *code));
-}
-
-
-MaybeObject* Map::UpdateCodeCache(Name* name, Code* code) {
+ HandleScope scope(isolate);
// Allocate the code cache if not present.
- if (code_cache()->IsFixedArray()) {
- Object* result;
- { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- set_code_cache(result);
+ if (map->code_cache()->IsFixedArray()) {
+ Handle<Object> result = isolate->factory()->NewCodeCache();
+ map->set_code_cache(*result);
}
// Update the code cache.
- return CodeCache::cast(code_cache())->Update(name, code);
+ Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
+ CodeCache::Update(code_cache, name, code);
}
@@ -7359,30 +7786,29 @@
}
-MaybeObject* CodeCache::Update(Name* name, Code* code) {
+void CodeCache::Update(
+ Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
// The number of monomorphic stubs for normal load/store/call IC's can grow to
// a large number and therefore they need to go into a hash table. They are
// used to load global properties from cells.
if (code->type() == Code::NORMAL) {
// Make sure that a hash table is allocated for the normal load code cache.
- if (normal_type_cache()->IsUndefined()) {
- Object* result;
- { MaybeObject* maybe_result =
- CodeCacheHashTable::Allocate(GetHeap(),
- CodeCacheHashTable::kInitialSize);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- set_normal_type_cache(result);
+ if (code_cache->normal_type_cache()->IsUndefined()) {
+ Handle<Object> result =
+ CodeCacheHashTable::New(code_cache->GetIsolate(),
+ CodeCacheHashTable::kInitialSize);
+ code_cache->set_normal_type_cache(*result);
}
- return UpdateNormalTypeCache(name, code);
+ UpdateNormalTypeCache(code_cache, name, code);
} else {
- ASSERT(default_cache()->IsFixedArray());
- return UpdateDefaultCache(name, code);
+ ASSERT(code_cache->default_cache()->IsFixedArray());
+ UpdateDefaultCache(code_cache, name, code);
}
}
-MaybeObject* CodeCache::UpdateDefaultCache(Name* name, Code* code) {
+void CodeCache::UpdateDefaultCache(
+ Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
// When updating the default code cache we disregard the type encoded in the
// flags. This allows call constant stubs to overwrite call field
// stubs, etc.
@@ -7390,37 +7816,40 @@
// First check whether we can update existing code cache without
// extending it.
- FixedArray* cache = default_cache();
+ Handle<FixedArray> cache = handle(code_cache->default_cache());
int length = cache->length();
- int deleted_index = -1;
- for (int i = 0; i < length; i += kCodeCacheEntrySize) {
- Object* key = cache->get(i);
- if (key->IsNull()) {
- if (deleted_index < 0) deleted_index = i;
- continue;
- }
- if (key->IsUndefined()) {
- if (deleted_index >= 0) i = deleted_index;
- cache->set(i + kCodeCacheEntryNameOffset, name);
- cache->set(i + kCodeCacheEntryCodeOffset, code);
- return this;
- }
- if (name->Equals(Name::cast(key))) {
- Code::Flags found =
- Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
- if (Code::RemoveTypeFromFlags(found) == flags) {
- cache->set(i + kCodeCacheEntryCodeOffset, code);
- return this;
+ {
+ DisallowHeapAllocation no_alloc;
+ int deleted_index = -1;
+ for (int i = 0; i < length; i += kCodeCacheEntrySize) {
+ Object* key = cache->get(i);
+ if (key->IsNull()) {
+ if (deleted_index < 0) deleted_index = i;
+ continue;
+ }
+ if (key->IsUndefined()) {
+ if (deleted_index >= 0) i = deleted_index;
+ cache->set(i + kCodeCacheEntryNameOffset, *name);
+ cache->set(i + kCodeCacheEntryCodeOffset, *code);
+ return;
+ }
+ if (name->Equals(Name::cast(key))) {
+ Code::Flags found =
+ Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
+ if (Code::RemoveTypeFromFlags(found) == flags) {
+ cache->set(i + kCodeCacheEntryCodeOffset, *code);
+ return;
+ }
}
}
- }
- // Reached the end of the code cache. If there were deleted
- // elements, reuse the space for the first of them.
- if (deleted_index >= 0) {
- cache->set(deleted_index + kCodeCacheEntryNameOffset, name);
- cache->set(deleted_index + kCodeCacheEntryCodeOffset, code);
- return this;
+ // Reached the end of the code cache. If there were deleted
+ // elements, reuse the space for the first of them.
+ if (deleted_index >= 0) {
+ cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
+ cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
+ return;
+ }
}
// Extend the code cache with some new entries (at least one). Must be a
@@ -7428,29 +7857,22 @@
int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
new_length = new_length - new_length % kCodeCacheEntrySize;
ASSERT((new_length % kCodeCacheEntrySize) == 0);
- Object* result;
- { MaybeObject* maybe_result = cache->CopySize(new_length);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
+ cache = FixedArray::CopySize(cache, new_length);
// Add the (name, code) pair to the new cache.
- cache = FixedArray::cast(result);
- cache->set(length + kCodeCacheEntryNameOffset, name);
- cache->set(length + kCodeCacheEntryCodeOffset, code);
- set_default_cache(cache);
- return this;
+ cache->set(length + kCodeCacheEntryNameOffset, *name);
+ cache->set(length + kCodeCacheEntryCodeOffset, *code);
+ code_cache->set_default_cache(*cache);
}
-MaybeObject* CodeCache::UpdateNormalTypeCache(Name* name, Code* code) {
+void CodeCache::UpdateNormalTypeCache(
+ Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
// Adding a new entry can cause a new cache to be allocated.
- CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
- Object* new_cache;
- { MaybeObject* maybe_new_cache = cache->Put(name, code);
- if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
- }
- set_normal_type_cache(new_cache);
- return this;
+ Handle<CodeCacheHashTable> cache(
+ CodeCacheHashTable::cast(code_cache->normal_type_cache()));
+ Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
+ code_cache->set_normal_type_cache(*new_cache);
}
@@ -7534,10 +7956,10 @@
// lookup not to create a new entry.
class CodeCacheHashTableKey : public HashTableKey {
public:
- CodeCacheHashTableKey(Name* name, Code::Flags flags)
- : name_(name), flags_(flags), code_(NULL) { }
+ CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
+ : name_(name), flags_(flags), code_() { }
- CodeCacheHashTableKey(Name* name, Code* code)
+ CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
: name_(name), flags_(code->flags()), code_(code) { }
@@ -7556,7 +7978,7 @@
return name->Hash() ^ flags;
}
- uint32_t Hash() { return NameFlagsHashHelper(name_, flags_); }
+ uint32_t Hash() { return NameFlagsHashHelper(*name_, flags_); }
uint32_t HashForObject(Object* obj) {
FixedArray* pair = FixedArray::cast(obj);
@@ -7566,58 +7988,60 @@
}
MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) {
- ASSERT(code_ != NULL);
+ Handle<Code> code = code_.ToHandleChecked();
Object* obj;
{ MaybeObject* maybe_obj = heap->AllocateFixedArray(2);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
FixedArray* pair = FixedArray::cast(obj);
- pair->set(0, name_);
- pair->set(1, code_);
+ pair->set(0, *name_);
+ pair->set(1, *code);
return pair;
}
+ Handle<FixedArray> AsHandle() {
+ Isolate* isolate = name_->GetIsolate();
+ CALL_HEAP_FUNCTION(isolate,
+ AsObject(isolate->heap()),
+ FixedArray);
+ }
+
private:
- Name* name_;
+ Handle<Name> name_;
Code::Flags flags_;
// TODO(jkummerow): We should be able to get by without this.
- Code* code_;
+ MaybeHandle<Code> code_;
};
Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
- CodeCacheHashTableKey key(name, flags);
+ DisallowHeapAllocation no_alloc;
+ CodeCacheHashTableKey key(handle(name), flags);
int entry = FindEntry(&key);
if (entry == kNotFound) return GetHeap()->undefined_value();
return get(EntryToIndex(entry) + 1);
}
-MaybeObject* CodeCacheHashTable::Put(Name* name, Code* code) {
+Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
+ Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
CodeCacheHashTableKey key(name, code);
- Object* obj;
- { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
- // Don't use |this|, as the table might have grown.
- CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj);
+ Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
- int entry = cache->FindInsertionEntry(key.Hash());
- Object* k;
- { MaybeObject* maybe_k = key.AsObject(GetHeap());
- if (!maybe_k->ToObject(&k)) return maybe_k;
- }
+ int entry = new_cache->FindInsertionEntry(key.Hash());
+ Handle<Object> k = key.AsHandle();
- cache->set(EntryToIndex(entry), k);
- cache->set(EntryToIndex(entry) + 1, code);
- cache->ElementAdded();
- return cache;
+ new_cache->set(EntryToIndex(entry), *k);
+ new_cache->set(EntryToIndex(entry) + 1, *code);
+ new_cache->ElementAdded();
+ return new_cache;
}
int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
- CodeCacheHashTableKey key(name, flags);
+ DisallowHeapAllocation no_alloc;
+ CodeCacheHashTableKey key(handle(name), flags);
int entry = FindEntry(&key);
return (entry == kNotFound) ? -1 : entry;
}
@@ -7632,41 +8056,27 @@
}
-void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache,
+void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
MapHandleList* maps,
Code::Flags flags,
Handle<Code> code) {
- Isolate* isolate = cache->GetIsolate();
- CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code));
-}
-
-
-MaybeObject* PolymorphicCodeCache::Update(MapHandleList* maps,
- Code::Flags flags,
- Code* code) {
- // Initialize cache if necessary.
- if (cache()->IsUndefined()) {
- Object* result;
- { MaybeObject* maybe_result =
- PolymorphicCodeCacheHashTable::Allocate(
- GetHeap(),
- PolymorphicCodeCacheHashTable::kInitialSize);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- set_cache(result);
+ Isolate* isolate = code_cache->GetIsolate();
+ if (code_cache->cache()->IsUndefined()) {
+ Handle<PolymorphicCodeCacheHashTable> result =
+ PolymorphicCodeCacheHashTable::New(
+ isolate,
+ PolymorphicCodeCacheHashTable::kInitialSize);
+ code_cache->set_cache(*result);
} else {
// This entry shouldn't be contained in the cache yet.
- ASSERT(PolymorphicCodeCacheHashTable::cast(cache())
+ ASSERT(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
->Lookup(maps, flags)->IsUndefined());
}
- PolymorphicCodeCacheHashTable* hash_table =
- PolymorphicCodeCacheHashTable::cast(cache());
- Object* new_cache;
- { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code);
- if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
- }
- set_cache(new_cache);
- return this;
+ Handle<PolymorphicCodeCacheHashTable> hash_table =
+ handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
+ Handle<PolymorphicCodeCacheHashTable> new_cache =
+ PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
+ code_cache->set_cache(*new_cache);
}
@@ -7688,8 +8098,10 @@
class PolymorphicCodeCacheHashTableKey : public HashTableKey {
public:
// Callers must ensure that |maps| outlives the newly constructed object.
- PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
- : maps_(maps),
+ PolymorphicCodeCacheHashTableKey(
+ Isolate* isolate, MapHandleList* maps, int code_flags)
+ : isolate_(isolate),
+ maps_(maps),
code_flags_(code_flags) {}
bool IsMatch(Object* other) {
@@ -7755,6 +8167,12 @@
return list;
}
+ Handle<FixedArray> AsHandle() {
+ CALL_HEAP_FUNCTION(isolate_,
+ AsObject(isolate_->heap()),
+ FixedArray);
+ }
+
private:
static MapHandleList* FromObject(Object* obj,
int* code_flags,
@@ -7768,6 +8186,7 @@
return maps;
}
+ Isolate* isolate_;
MapHandleList* maps_; // weak.
int code_flags_;
static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
@@ -7775,30 +8194,29 @@
Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
- int code_flags) {
- PolymorphicCodeCacheHashTableKey key(maps, code_flags);
+ int code_kind) {
+ DisallowHeapAllocation no_alloc;
+ PolymorphicCodeCacheHashTableKey key(GetIsolate(), maps, code_kind);
int entry = FindEntry(&key);
if (entry == kNotFound) return GetHeap()->undefined_value();
return get(EntryToIndex(entry) + 1);
}
-MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps,
- int code_flags,
- Code* code) {
- PolymorphicCodeCacheHashTableKey key(maps, code_flags);
- Object* obj;
- { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
- PolymorphicCodeCacheHashTable* cache =
- reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj);
+Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
+ Handle<PolymorphicCodeCacheHashTable> hash_table,
+ MapHandleList* maps,
+ int code_kind,
+ Handle<Code> code) {
+ PolymorphicCodeCacheHashTableKey key(
+ hash_table->GetIsolate(), maps, code_kind);
+ Handle<PolymorphicCodeCacheHashTable> cache =
+ EnsureCapacity(hash_table, 1, &key);
int entry = cache->FindInsertionEntry(key.Hash());
- { MaybeObject* maybe_obj = key.AsObject(GetHeap());
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
- cache->set(EntryToIndex(entry), obj);
- cache->set(EntryToIndex(entry) + 1, code);
+
+ Handle<FixedArray> obj = key.AsHandle();
+ cache->set(EntryToIndex(entry), *obj);
+ cache->set(EntryToIndex(entry) + 1, *code);
cache->ElementAdded();
return cache;
}
@@ -7885,6 +8303,15 @@
}
+Handle<FixedArray> FixedArray::CopySize(
+ Handle<FixedArray> array, int new_length, PretenureFlag pretenure) {
+ Isolate* isolate = array->GetIsolate();
+ CALL_HEAP_FUNCTION(isolate,
+ array->CopySize(new_length, pretenure),
+ FixedArray);
+}
+
+
void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
@@ -8015,16 +8442,27 @@
(left_details.type() == CONSTANT &&
right_details.type() == CONSTANT &&
left->GetValue(descriptor) != right->GetValue(descriptor))) {
+ ASSERT(left_details.type() == CONSTANT || left_details.type() == FIELD);
+ ASSERT(right_details.type() == CONSTANT || right_details.type() == FIELD);
Representation representation = left_details.representation().generalize(
right_details.representation());
- FieldDescriptor d(handle(left->GetKey(descriptor)),
+ Handle<HeapType> left_type = (left_details.type() == FIELD)
+ ? handle(left->GetFieldType(descriptor), isolate)
+ : left->GetValue(descriptor)->OptimalType(isolate, representation);
+ Handle<HeapType> right_type = (right_details.type() == FIELD)
+ ? handle(right->GetFieldType(descriptor), isolate)
+ : right->GetValue(descriptor)->OptimalType(isolate, representation);
+ Handle<HeapType> field_type = Map::GeneralizeFieldType(
+ left_type, right_type, isolate);
+ FieldDescriptor d(handle(left->GetKey(descriptor), isolate),
current_offset++,
+ field_type,
right_details.attributes(),
representation);
result->Set(descriptor, &d);
} else {
- Descriptor d(handle(right->GetKey(descriptor)),
- handle(right->GetValue(descriptor), right->GetIsolate()),
+ Descriptor d(handle(right->GetKey(descriptor), isolate),
+ handle(right->GetValue(descriptor), isolate),
right_details);
result->Set(descriptor, &d);
}
@@ -8033,16 +8471,27 @@
// |valid| -> |new_size|
for (; descriptor < new_size; descriptor++) {
PropertyDetails right_details = right->GetDetails(descriptor);
- if (right_details.type() == FIELD ||
- (store_mode == FORCE_FIELD && descriptor == modify_index)) {
- FieldDescriptor d(handle(right->GetKey(descriptor)),
+ if (right_details.type() == FIELD) {
+ FieldDescriptor d(handle(right->GetKey(descriptor), isolate),
current_offset++,
+ handle(right->GetFieldType(descriptor), isolate),
right_details.attributes(),
right_details.representation());
result->Set(descriptor, &d);
+ } else if (store_mode == FORCE_FIELD && descriptor == modify_index) {
+ ASSERT_EQ(CONSTANT, right_details.type());
+ Representation field_representation = right_details.representation();
+ Handle<HeapType> field_type = right->GetValue(descriptor)->OptimalType(
+ isolate, field_representation);
+ FieldDescriptor d(handle(right->GetKey(descriptor), isolate),
+ current_offset++,
+ field_type,
+ right_details.attributes(),
+ field_representation);
+ result->Set(descriptor, &d);
} else {
- Descriptor d(handle(right->GetKey(descriptor)),
- handle(right->GetValue(descriptor), right->GetIsolate()),
+ Descriptor d(handle(right->GetKey(descriptor), isolate),
+ handle(right->GetValue(descriptor), isolate),
right_details);
result->Set(descriptor, &d);
}
@@ -8707,6 +9156,64 @@
}
+
+template <typename SourceChar>
+static void CalculateLineEndsImpl(Isolate* isolate,
+ List<int>* line_ends,
+ Vector<const SourceChar> src,
+ bool include_ending_line) {
+ const int src_len = src.length();
+ StringSearch<uint8_t, SourceChar> search(isolate, STATIC_ASCII_VECTOR("\n"));
+
+ // Find and record line ends.
+ int position = 0;
+ while (position != -1 && position < src_len) {
+ position = search.Search(src, position);
+ if (position != -1) {
+ line_ends->Add(position);
+ position++;
+ } else if (include_ending_line) {
+ // Even if the last line misses a line end, it is counted.
+ line_ends->Add(src_len);
+ return;
+ }
+ }
+}
+
+
+Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
+ bool include_ending_line) {
+ src = Flatten(src);
+ // Rough estimate of line count based on a roughly estimated average
+ // length of (unpacked) code.
+ int line_count_estimate = src->length() >> 4;
+ List<int> line_ends(line_count_estimate);
+ Isolate* isolate = src->GetIsolate();
+ { DisallowHeapAllocation no_allocation; // ensure vectors stay valid.
+ // Dispatch on type of strings.
+ String::FlatContent content = src->GetFlatContent();
+ ASSERT(content.IsFlat());
+ if (content.IsAscii()) {
+ CalculateLineEndsImpl(isolate,
+ &line_ends,
+ content.ToOneByteVector(),
+ include_ending_line);
+ } else {
+ CalculateLineEndsImpl(isolate,
+ &line_ends,
+ content.ToUC16Vector(),
+ include_ending_line);
+ }
+ }
+ int line_count = line_ends.length();
+ Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
+ for (int i = 0; i < line_count; i++) {
+ array->set(i, Smi::FromInt(line_ends[i]));
+ }
+ return array;
+}
+
+
// Compares the contents of two strings by reading and comparing
// int-sized blocks of characters.
template <typename Char>
@@ -9899,20 +10406,171 @@
}
-MaybeObject* Oddball::Initialize(Heap* heap,
- const char* to_string,
- Object* to_number,
- byte kind) {
- String* internalized_to_string;
- { MaybeObject* maybe_string =
- heap->InternalizeUtf8String(
- CStrVector(to_string));
- if (!maybe_string->To(&internalized_to_string)) return maybe_string;
+void Oddball::Initialize(Isolate* isolate,
+ Handle<Oddball> oddball,
+ const char* to_string,
+ Handle<Object> to_number,
+ byte kind) {
+ Handle<String> internalized_to_string =
+ isolate->factory()->InternalizeUtf8String(CStrVector(to_string));
+ oddball->set_to_string(*internalized_to_string);
+ oddball->set_to_number(*to_number);
+ oddball->set_kind(kind);
+}
+
+
+void Script::InitLineEnds(Handle<Script> script) {
+ if (!script->line_ends()->IsUndefined()) return;
+
+ Isolate* isolate = script->GetIsolate();
+
+ if (!script->source()->IsString()) {
+ ASSERT(script->source()->IsUndefined());
+ Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
+ script->set_line_ends(*empty);
+ ASSERT(script->line_ends()->IsFixedArray());
+ return;
}
- set_to_string(internalized_to_string);
- set_to_number(to_number);
- set_kind(kind);
- return this;
+
+ Handle<String> src(String::cast(script->source()), isolate);
+
+ Handle<FixedArray> array = String::CalculateLineEnds(src, true);
+
+ if (*array != isolate->heap()->empty_fixed_array()) {
+ array->set_map(isolate->heap()->fixed_cow_array_map());
+ }
+
+ script->set_line_ends(*array);
+ ASSERT(script->line_ends()->IsFixedArray());
+}
+
+
+int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
+ int line_number = GetLineNumber(script, code_pos);
+ if (line_number == -1) return -1;
+
+ DisallowHeapAllocation no_allocation;
+ FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
+ line_number = line_number - script->line_offset()->value();
+ if (line_number == 0) return code_pos + script->column_offset()->value();
+ int prev_line_end_pos =
+ Smi::cast(line_ends_array->get(line_number - 1))->value();
+ return code_pos - (prev_line_end_pos + 1);
+}
+
+
+int Script::GetLineNumberWithArray(int code_pos) {
+ DisallowHeapAllocation no_allocation;
+ ASSERT(line_ends()->IsFixedArray());
+ FixedArray* line_ends_array = FixedArray::cast(line_ends());
+ int line_ends_len = line_ends_array->length();
+ if (line_ends_len == 0) return -1;
+
+ if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
+ return line_offset()->value();
+ }
+
+ int left = 0;
+ int right = line_ends_len;
+ while (int half = (right - left) / 2) {
+ if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
+ right -= half;
+ } else {
+ left += half;
+ }
+ }
+ return right + line_offset()->value();
+}
+
+
+int Script::GetLineNumber(Handle<Script> script, int code_pos) {
+ InitLineEnds(script);
+ return script->GetLineNumberWithArray(code_pos);
+}
+
+
+int Script::GetLineNumber(int code_pos) {
+ DisallowHeapAllocation no_allocation;
+ if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
+
+ // Slow mode: we do not have line_ends. We have to iterate through source.
+ if (!source()->IsString()) return -1;
+
+ String* source_string = String::cast(source());
+ int line = 0;
+ int len = source_string->length();
+ for (int pos = 0; pos < len; pos++) {
+ if (pos == code_pos) break;
+ if (source_string->Get(pos) == '\n') line++;
+ }
+ return line;
+}
+
+
+Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
+ Isolate* isolate = script->GetIsolate();
+ Handle<String> name_or_source_url_key =
+ isolate->factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("nameOrSourceURL"));
+ Handle<JSObject> script_wrapper = Script::GetWrapper(script);
+ Handle<Object> property = Object::GetProperty(
+ script_wrapper, name_or_source_url_key).ToHandleChecked();
+ ASSERT(property->IsJSFunction());
+ Handle<JSFunction> method = Handle<JSFunction>::cast(property);
+ Handle<Object> result;
+ // Do not check against pending exception, since this function may be called
+ // when an exception has already been pending.
+ if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
+ return isolate->factory()->undefined_value();
+ }
+ return result;
+}
+
+
+// Wrappers for scripts are kept alive and cached in weak global
+// handles referred from foreign objects held by the scripts as long as
+// they are used. When they are not used anymore, the garbage
+// collector will call the weak callback on the global handle
+// associated with the wrapper and get rid of both the wrapper and the
+// handle.
+static void ClearWrapperCache(
+ const v8::WeakCallbackData<v8::Value, void>& data) {
+ Object** location = reinterpret_cast<Object**>(data.GetParameter());
+ JSValue* wrapper = JSValue::cast(*location);
+ Foreign* foreign = Script::cast(wrapper->value())->wrapper();
+ ASSERT_EQ(foreign->foreign_address(), reinterpret_cast<Address>(location));
+ foreign->set_foreign_address(0);
+ GlobalHandles::Destroy(location);
+ Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate());
+ isolate->counters()->script_wrappers()->Decrement();
+}
+
+
+Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
+ if (script->wrapper()->foreign_address() != NULL) {
+ // Return a handle for the existing script wrapper from the cache.
+ return Handle<JSValue>(
+ *reinterpret_cast<JSValue**>(script->wrapper()->foreign_address()));
+ }
+ Isolate* isolate = script->GetIsolate();
+ // Construct a new script wrapper.
+ isolate->counters()->script_wrappers()->Increment();
+ Handle<JSFunction> constructor = isolate->script_function();
+ Handle<JSValue> result =
+ Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
+
+ result->set_value(*script);
+
+ // Create a new weak global handle and use it to cache the wrapper
+ // for future use. The cache will automatically be cleared by the
+ // garbage collector when it is not used anymore.
+ Handle<Object> handle = isolate->global_handles()->Create(*result);
+ GlobalHandles::MakeWeak(handle.location(),
+ reinterpret_cast<void*>(handle.location()),
+ &ClearWrapperCache);
+ script->wrapper()->set_foreign_address(
+ reinterpret_cast<Address>(handle.location()));
+ return result;
}
@@ -11491,35 +12149,41 @@
}
-void Map::AddDependentCompilationInfo(DependentCode::DependencyGroup group,
+// static
+void Map::AddDependentCompilationInfo(Handle<Map> map,
+ DependentCode::DependencyGroup group,
CompilationInfo* info) {
- Handle<DependentCode> dep(dependent_code());
Handle<DependentCode> codes =
- DependentCode::Insert(dep, group, info->object_wrapper());
- if (*codes != dependent_code()) set_dependent_code(*codes);
- info->dependencies(group)->Add(Handle<HeapObject>(this), info->zone());
+ DependentCode::Insert(handle(map->dependent_code(), info->isolate()),
+ group, info->object_wrapper());
+ if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
+ info->dependencies(group)->Add(map, info->zone());
}
-void Map::AddDependentCode(DependentCode::DependencyGroup group,
+// static
+void Map::AddDependentCode(Handle<Map> map,
+ DependentCode::DependencyGroup group,
Handle<Code> code) {
Handle<DependentCode> codes = DependentCode::Insert(
- Handle<DependentCode>(dependent_code()), group, code);
- if (*codes != dependent_code()) set_dependent_code(*codes);
+ Handle<DependentCode>(map->dependent_code()), group, code);
+ if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
}
-void Map::AddDependentIC(Handle<Code> stub) {
+// static
+void Map::AddDependentIC(Handle<Map> map,
+ Handle<Code> stub) {
ASSERT(stub->next_code_link()->IsUndefined());
- int n = dependent_code()->number_of_entries(DependentCode::kWeakICGroup);
+ int n = map->dependent_code()->number_of_entries(DependentCode::kWeakICGroup);
if (n == 0) {
// Slow path: insert the head of the list with possible heap allocation.
- AddDependentCode(DependentCode::kWeakICGroup, stub);
+ Map::AddDependentCode(map, DependentCode::kWeakICGroup, stub);
} else {
// Fast path: link the stub to the existing head of the list without any
// heap allocation.
ASSERT(n == 1);
- dependent_code()->AddToDependentICList(stub);
+ map->dependent_code()->AddToDependentICList(stub);
}
}
@@ -11747,9 +12411,9 @@
}
-Handle<Object> JSObject::SetPrototype(Handle<JSObject> object,
- Handle<Object> value,
- bool skip_hidden_prototypes) {
+MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
+ Handle<Object> value,
+ bool skip_hidden_prototypes) {
#ifdef DEBUG
int size = object->Size();
#endif
@@ -11772,8 +12436,7 @@
Handle<Object> args[] = { object };
Handle<Object> error = isolate->factory()->NewTypeError(
"non_extensible_proto", HandleVector(args, ARRAY_SIZE(args)));
- isolate->Throw(*error);
- return Handle<Object>();
+ return isolate->Throw<Object>(error);
}
// Before we can set the prototype we need to be sure
@@ -11787,8 +12450,7 @@
// Cycle detected.
Handle<Object> error = isolate->factory()->NewError(
"cyclic_proto", HandleVector<Object>(NULL, 0));
- isolate->Throw(*error);
- return Handle<Object>();
+ return isolate->Throw<Object>(error);
}
}
@@ -11937,13 +12599,12 @@
v8::AccessorGetterCallback call_fun =
v8::ToCData<v8::AccessorGetterCallback>(fun_obj);
if (call_fun == NULL) return isolate->factory()->undefined_value();
- Handle<JSObject> self = Handle<JSObject>::cast(receiver);
Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder);
Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
Handle<String> key = isolate->factory()->NumberToString(number);
- LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
+ LOG(isolate, ApiNamedPropertyAccess("load", *holder_handle, *key));
PropertyCallbackArguments
- args(isolate, data->data(), *self, *holder_handle);
+ args(isolate, data->data(), *receiver, *holder_handle);
v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key));
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
if (result.IsEmpty()) return isolate->factory()->undefined_value();
@@ -12885,26 +13546,15 @@
void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array,
uint32_t index,
Handle<Object> value) {
- CALL_HEAP_FUNCTION_VOID(array->GetIsolate(),
- array->JSArrayUpdateLengthFromIndex(index, *value));
-}
-
-
-MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
- Object* value) {
uint32_t old_len = 0;
- CHECK(length()->ToArrayIndex(&old_len));
+ CHECK(array->length()->ToArrayIndex(&old_len));
// Check to see if we need to update the length. For now, we make
// sure that the length stays within 32-bits (unsigned).
if (index >= old_len && index != 0xffffffff) {
- Object* len;
- { MaybeObject* maybe_len =
- GetHeap()->NumberFromDouble(static_cast<double>(index) + 1);
- if (!maybe_len->ToObject(&len)) return maybe_len;
- }
- set_length(len);
+ Handle<Object> len = array->GetIsolate()->factory()->NewNumber(
+ static_cast<double>(index) + 1);
+ array->set_length(*len);
}
- return value;
}
@@ -12927,7 +13577,7 @@
PropertyCallbackArguments
args(isolate, interceptor->data(), *receiver, *object);
v8::Handle<v8::Value> result = args.Call(getter, index);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
if (!result.IsEmpty()) {
Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
result_internal->VerifyApiCallResultType();
@@ -13249,6 +13899,55 @@
}
+// Compute the property keys from the interceptor.
+// TODO(rossberg): support symbols in API, and filter here if needed.
+MaybeHandle<JSArray> JSObject::GetKeysForNamedInterceptor(
+ Handle<JSObject> object, Handle<JSReceiver> receiver) {
+ Isolate* isolate = receiver->GetIsolate();
+ Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
+ PropertyCallbackArguments
+ args(isolate, interceptor->data(), *receiver, *object);
+ v8::Handle<v8::Array> result;
+ if (!interceptor->enumerator()->IsUndefined()) {
+ v8::NamedPropertyEnumeratorCallback enum_fun =
+ v8::ToCData<v8::NamedPropertyEnumeratorCallback>(
+ interceptor->enumerator());
+ LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
+ result = args.Call(enum_fun);
+ }
+ if (result.IsEmpty()) return MaybeHandle<JSArray>();
+#if ENABLE_EXTRA_CHECKS
+ CHECK(v8::Utils::OpenHandle(*result)->IsJSObject());
+#endif
+ // Rebox before returning.
+ return handle(*v8::Utils::OpenHandle(*result), isolate);
+}
+
+
+// Compute the element keys from the interceptor.
+MaybeHandle<JSArray> JSObject::GetKeysForIndexedInterceptor(
+ Handle<JSObject> object, Handle<JSReceiver> receiver) {
+ Isolate* isolate = receiver->GetIsolate();
+ Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
+ PropertyCallbackArguments
+ args(isolate, interceptor->data(), *receiver, *object);
+ v8::Handle<v8::Array> result;
+ if (!interceptor->enumerator()->IsUndefined()) {
+ v8::IndexedPropertyEnumeratorCallback enum_fun =
+ v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
+ interceptor->enumerator());
+ LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
+ result = args.Call(enum_fun);
+ }
+ if (result.IsEmpty()) return MaybeHandle<JSArray>();
+#if ENABLE_EXTRA_CHECKS
+ CHECK(v8::Utils::OpenHandle(*result)->IsJSObject());
+#endif
+ // Rebox before returning.
+ return handle(*v8::Utils::OpenHandle(*result), isolate);
+}
+
+
bool JSObject::HasRealNamedProperty(Handle<JSObject> object,
Handle<Name> key) {
Isolate* isolate = object->GetIsolate();
@@ -14100,6 +14799,19 @@
template<typename Derived, typename Shape, typename Key>
+Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
+ Handle<Derived> table,
+ int n,
+ Key key,
+ PretenureFlag pretenure) {
+ Isolate* isolate = table->GetIsolate();
+ CALL_HEAP_FUNCTION(isolate,
+ table->EnsureCapacity(n, key, pretenure),
+ Derived);
+}
+
+
+template<typename Derived, typename Shape, typename Key>
Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
Key key) {
int capacity = table->Capacity();
@@ -14182,6 +14894,10 @@
template MaybeObject* Dictionary<NameDictionary, NameDictionaryShape, Name*>::
Allocate(Heap* heap, int n, PretenureFlag pretenure);
+template Handle<NameDictionary>
+Dictionary<NameDictionary, NameDictionaryShape, Name*>::
+ New(Isolate* isolate, int n, PretenureFlag pretenure);
+
template MaybeObject*
Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
AtPut(uint32_t, Object*);
@@ -14236,6 +14952,10 @@
template Handle<NameDictionary>
HashTable<NameDictionary, NameDictionaryShape, Name*>::
+ New(Isolate*, int, MinimumCapacity, PretenureFlag);
+
+template Handle<NameDictionary>
+HashTable<NameDictionary, NameDictionaryShape, Name*>::
Shrink(Handle<NameDictionary>, Name* n);
template Handle<SeededNumberDictionary>
@@ -14322,107 +15042,88 @@
Handle<Object> JSObject::PrepareSlowElementsForSort(
Handle<JSObject> object, uint32_t limit) {
- CALL_HEAP_FUNCTION(object->GetIsolate(),
- object->PrepareSlowElementsForSort(limit),
- Object);
-}
-
-
-// Collates undefined and unexisting elements below limit from position
-// zero of the elements. The object stays in Dictionary mode.
-MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
- ASSERT(HasDictionaryElements());
+ ASSERT(object->HasDictionaryElements());
+ Isolate* isolate = object->GetIsolate();
// Must stay in dictionary mode, either because of requires_slow_elements,
// or because we are not going to sort (and therefore compact) all of the
// elements.
- SeededNumberDictionary* dict = element_dictionary();
- HeapNumber* result_double = NULL;
- if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
- // Allocate space for result before we start mutating the object.
- Object* new_double;
- { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0);
- if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
- }
- result_double = HeapNumber::cast(new_double);
- }
-
- Object* obj;
- { MaybeObject* maybe_obj =
- SeededNumberDictionary::Allocate(GetHeap(), dict->NumberOfElements());
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
- SeededNumberDictionary* new_dict = SeededNumberDictionary::cast(obj);
-
- DisallowHeapAllocation no_alloc;
+ Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
+ Handle<SeededNumberDictionary> new_dict =
+ isolate->factory()->NewSeededNumberDictionary(dict->NumberOfElements());
uint32_t pos = 0;
uint32_t undefs = 0;
int capacity = dict->Capacity();
+ Handle<Smi> bailout(Smi::FromInt(-1), isolate);
+ // Entry to the new dictionary does not cause it to grow, as we have
+ // allocated one that is large enough for all entries.
+ DisallowHeapAllocation no_gc;
for (int i = 0; i < capacity; i++) {
Object* k = dict->KeyAt(i);
- if (dict->IsKey(k)) {
- ASSERT(k->IsNumber());
- ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
- ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
- ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
- Object* value = dict->ValueAt(i);
- PropertyDetails details = dict->DetailsAt(i);
- if (details.type() == CALLBACKS || details.IsReadOnly()) {
- // Bail out and do the sorting of undefineds and array holes in JS.
- // Also bail out if the element is not supposed to be moved.
- return Smi::FromInt(-1);
- }
- uint32_t key = NumberToUint32(k);
- // In the following we assert that adding the entry to the new dictionary
- // does not cause GC. This is the case because we made sure to allocate
- // the dictionary big enough above, so it need not grow.
- if (key < limit) {
- if (value->IsUndefined()) {
- undefs++;
- } else {
- if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
- // Adding an entry with the key beyond smi-range requires
- // allocation. Bailout.
- return Smi::FromInt(-1);
- }
- new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked();
- pos++;
- }
+ if (!dict->IsKey(k)) continue;
+
+ ASSERT(k->IsNumber());
+ ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
+ ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
+ ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
+
+ HandleScope scope(isolate);
+ Handle<Object> value(dict->ValueAt(i), isolate);
+ PropertyDetails details = dict->DetailsAt(i);
+ if (details.type() == CALLBACKS || details.IsReadOnly()) {
+ // Bail out and do the sorting of undefineds and array holes in JS.
+ // Also bail out if the element is not supposed to be moved.
+ return bailout;
+ }
+
+ uint32_t key = NumberToUint32(k);
+ if (key < limit) {
+ if (value->IsUndefined()) {
+ undefs++;
+ } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
+ // Adding an entry with the key beyond smi-range requires
+ // allocation. Bailout.
+ return bailout;
} else {
- if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
- // Adding an entry with the key beyond smi-range requires
- // allocation. Bailout.
- return Smi::FromInt(-1);
- }
- new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
+ Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
+ new_dict, pos, value, details);
+ ASSERT(result.is_identical_to(new_dict));
+ USE(result);
+ pos++;
}
+ } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
+ // Adding an entry with the key beyond smi-range requires
+ // allocation. Bailout.
+ return bailout;
+ } else {
+ Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
+ new_dict, key, value, details);
+ ASSERT(result.is_identical_to(new_dict));
+ USE(result);
}
}
uint32_t result = pos;
PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0);
- Heap* heap = GetHeap();
while (undefs > 0) {
if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
// Adding an entry with the key beyond smi-range requires
// allocation. Bailout.
- return Smi::FromInt(-1);
+ return bailout;
}
- new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
- ToObjectUnchecked();
+ HandleScope scope(isolate);
+ Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
+ new_dict, pos, isolate->factory()->undefined_value(), no_details);
+ ASSERT(result.is_identical_to(new_dict));
+ USE(result);
pos++;
undefs--;
}
- set_elements(new_dict);
+ object->set_elements(*new_dict);
- if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
- return Smi::FromInt(static_cast<int>(result));
- }
-
- ASSERT_NE(NULL, result_double);
- result_double->set_value(static_cast<double>(result));
- return result_double;
+ AllowHeapAllocation allocate_return_value;
+ return isolate->factory()->NewNumberFromUint(result);
}
@@ -14593,11 +15294,14 @@
}
-Object* ExternalUint8ClampedArray::SetValue(uint32_t index, Object* value) {
+Handle<Object> ExternalUint8ClampedArray::SetValue(
+ Handle<ExternalUint8ClampedArray> array,
+ uint32_t index,
+ Handle<Object> value) {
uint8_t clamped_value = 0;
- if (index < static_cast<uint32_t>(length())) {
+ if (index < static_cast<uint32_t>(array->length())) {
if (value->IsSmi()) {
- int int_value = Smi::cast(value)->value();
+ int int_value = Handle<Smi>::cast(value)->value();
if (int_value < 0) {
clamped_value = 0;
} else if (int_value > 255) {
@@ -14606,7 +15310,7 @@
clamped_value = static_cast<uint8_t>(int_value);
}
} else if (value->IsHeapNumber()) {
- double double_value = HeapNumber::cast(value)->value();
+ double double_value = Handle<HeapNumber>::cast(value)->value();
if (!(double_value > 0)) {
// NaN and less than zero clamp to zero.
clamped_value = 0;
@@ -14622,32 +15326,25 @@
// converted to a number type further up in the call chain.
ASSERT(value->IsUndefined());
}
- set(index, clamped_value);
+ array->set(index, clamped_value);
}
- return Smi::FromInt(clamped_value);
-}
-
-
-Handle<Object> ExternalUint8ClampedArray::SetValue(
- Handle<ExternalUint8ClampedArray> array,
- uint32_t index,
- Handle<Object> value) {
- return Handle<Object>(array->SetValue(index, *value), array->GetIsolate());
+ return handle(Smi::FromInt(clamped_value), array->GetIsolate());
}
template<typename ExternalArrayClass, typename ValueType>
-static MaybeObject* ExternalArrayIntSetter(Heap* heap,
- ExternalArrayClass* receiver,
- uint32_t index,
- Object* value) {
+static Handle<Object> ExternalArrayIntSetter(
+ Isolate* isolate,
+ Handle<ExternalArrayClass> receiver,
+ uint32_t index,
+ Handle<Object> value) {
ValueType cast_value = 0;
if (index < static_cast<uint32_t>(receiver->length())) {
if (value->IsSmi()) {
- int int_value = Smi::cast(value)->value();
+ int int_value = Handle<Smi>::cast(value)->value();
cast_value = static_cast<ValueType>(int_value);
} else if (value->IsHeapNumber()) {
- double double_value = HeapNumber::cast(value)->value();
+ double double_value = Handle<HeapNumber>::cast(value)->value();
cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
} else {
// Clamp undefined to zero (default). All other types have been
@@ -14656,88 +15353,47 @@
}
receiver->set(index, cast_value);
}
- return heap->NumberFromInt32(cast_value);
+ return isolate->factory()->NewNumberFromInt(cast_value);
}
Handle<Object> ExternalInt8Array::SetValue(Handle<ExternalInt8Array> array,
uint32_t index,
Handle<Object> value) {
- CALL_HEAP_FUNCTION(array->GetIsolate(),
- array->SetValue(index, *value),
- Object);
+ return ExternalArrayIntSetter<ExternalInt8Array, int8_t>(
+ array->GetIsolate(), array, index, value);
}
-MaybeObject* ExternalInt8Array::SetValue(uint32_t index, Object* value) {
- return ExternalArrayIntSetter<ExternalInt8Array, int8_t>
- (GetHeap(), this, index, value);
+Handle<Object> ExternalUint8Array::SetValue(Handle<ExternalUint8Array> array,
+ uint32_t index,
+ Handle<Object> value) {
+ return ExternalArrayIntSetter<ExternalUint8Array, uint8_t>(
+ array->GetIsolate(), array, index, value);
}
-Handle<Object> ExternalUint8Array::SetValue(
- Handle<ExternalUint8Array> array,
- uint32_t index,
- Handle<Object> value) {
- CALL_HEAP_FUNCTION(array->GetIsolate(),
- array->SetValue(index, *value),
- Object);
+Handle<Object> ExternalInt16Array::SetValue(Handle<ExternalInt16Array> array,
+ uint32_t index,
+ Handle<Object> value) {
+ return ExternalArrayIntSetter<ExternalInt16Array, int16_t>(
+ array->GetIsolate(), array, index, value);
}
-MaybeObject* ExternalUint8Array::SetValue(uint32_t index,
- Object* value) {
- return ExternalArrayIntSetter<ExternalUint8Array, uint8_t>
- (GetHeap(), this, index, value);
-}
-
-
-Handle<Object> ExternalInt16Array::SetValue(
- Handle<ExternalInt16Array> array,
- uint32_t index,
- Handle<Object> value) {
- CALL_HEAP_FUNCTION(array->GetIsolate(),
- array->SetValue(index, *value),
- Object);
-}
-
-
-MaybeObject* ExternalInt16Array::SetValue(uint32_t index,
- Object* value) {
- return ExternalArrayIntSetter<ExternalInt16Array, int16_t>
- (GetHeap(), this, index, value);
-}
-
-
-Handle<Object> ExternalUint16Array::SetValue(
- Handle<ExternalUint16Array> array,
- uint32_t index,
- Handle<Object> value) {
- CALL_HEAP_FUNCTION(array->GetIsolate(),
- array->SetValue(index, *value),
- Object);
-}
-
-
-MaybeObject* ExternalUint16Array::SetValue(uint32_t index,
- Object* value) {
- return ExternalArrayIntSetter<ExternalUint16Array, uint16_t>
- (GetHeap(), this, index, value);
+Handle<Object> ExternalUint16Array::SetValue(Handle<ExternalUint16Array> array,
+ uint32_t index,
+ Handle<Object> value) {
+ return ExternalArrayIntSetter<ExternalUint16Array, uint16_t>(
+ array->GetIsolate(), array, index, value);
}
Handle<Object> ExternalInt32Array::SetValue(Handle<ExternalInt32Array> array,
- uint32_t index,
- Handle<Object> value) {
- CALL_HEAP_FUNCTION(array->GetIsolate(),
- array->SetValue(index, *value),
- Object);
-}
-
-
-MaybeObject* ExternalInt32Array::SetValue(uint32_t index, Object* value) {
- return ExternalArrayIntSetter<ExternalInt32Array, int32_t>
- (GetHeap(), this, index, value);
+ uint32_t index,
+ Handle<Object> value) {
+ return ExternalArrayIntSetter<ExternalInt32Array, int32_t>(
+ array->GetIsolate(), array, index, value);
}
@@ -14745,30 +15401,22 @@
Handle<ExternalUint32Array> array,
uint32_t index,
Handle<Object> value) {
- CALL_HEAP_FUNCTION(array->GetIsolate(),
- array->SetValue(index, *value),
- Object);
-}
-
-
-MaybeObject* ExternalUint32Array::SetValue(uint32_t index, Object* value) {
uint32_t cast_value = 0;
- Heap* heap = GetHeap();
- if (index < static_cast<uint32_t>(length())) {
+ if (index < static_cast<uint32_t>(array->length())) {
if (value->IsSmi()) {
- int int_value = Smi::cast(value)->value();
+ int int_value = Handle<Smi>::cast(value)->value();
cast_value = static_cast<uint32_t>(int_value);
} else if (value->IsHeapNumber()) {
- double double_value = HeapNumber::cast(value)->value();
+ double double_value = Handle<HeapNumber>::cast(value)->value();
cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
} else {
// Clamp undefined to zero (default). All other types have been
// converted to a number type further up in the call chain.
ASSERT(value->IsUndefined());
}
- set(index, cast_value);
+ array->set(index, cast_value);
}
- return heap->NumberFromUint32(cast_value);
+ return array->GetIsolate()->factory()->NewNumberFromUint(cast_value);
}
@@ -14776,30 +15424,22 @@
Handle<ExternalFloat32Array> array,
uint32_t index,
Handle<Object> value) {
- CALL_HEAP_FUNCTION(array->GetIsolate(),
- array->SetValue(index, *value),
- Object);
-}
-
-
-MaybeObject* ExternalFloat32Array::SetValue(uint32_t index, Object* value) {
float cast_value = static_cast<float>(OS::nan_value());
- Heap* heap = GetHeap();
- if (index < static_cast<uint32_t>(length())) {
+ if (index < static_cast<uint32_t>(array->length())) {
if (value->IsSmi()) {
- int int_value = Smi::cast(value)->value();
+ int int_value = Handle<Smi>::cast(value)->value();
cast_value = static_cast<float>(int_value);
} else if (value->IsHeapNumber()) {
- double double_value = HeapNumber::cast(value)->value();
+ double double_value = Handle<HeapNumber>::cast(value)->value();
cast_value = static_cast<float>(double_value);
} else {
// Clamp undefined to NaN (default). All other types have been
// converted to a number type further up in the call chain.
ASSERT(value->IsUndefined());
}
- set(index, cast_value);
+ array->set(index, cast_value);
}
- return heap->AllocateHeapNumber(cast_value);
+ return array->GetIsolate()->factory()->NewNumber(cast_value);
}
@@ -14807,29 +15447,18 @@
Handle<ExternalFloat64Array> array,
uint32_t index,
Handle<Object> value) {
- CALL_HEAP_FUNCTION(array->GetIsolate(),
- array->SetValue(index, *value),
- Object);
-}
-
-
-MaybeObject* ExternalFloat64Array::SetValue(uint32_t index, Object* value) {
double double_value = OS::nan_value();
- Heap* heap = GetHeap();
- if (index < static_cast<uint32_t>(length())) {
- if (value->IsSmi()) {
- int int_value = Smi::cast(value)->value();
- double_value = static_cast<double>(int_value);
- } else if (value->IsHeapNumber()) {
- double_value = HeapNumber::cast(value)->value();
+ if (index < static_cast<uint32_t>(array->length())) {
+ if (value->IsNumber()) {
+ double_value = value->Number();
} else {
// Clamp undefined to NaN (default). All other types have been
// converted to a number type further up in the call chain.
ASSERT(value->IsUndefined());
}
- set(index, double_value);
+ array->set(index, double_value);
}
- return heap->AllocateHeapNumber(double_value);
+ return array->GetIsolate()->factory()->NewNumber(double_value);
}
@@ -15042,7 +15671,7 @@
Handle<SharedFunctionInfo> shared(context->closure()->shared());
StringSharedKey key(src, shared, FLAG_use_strict ? STRICT : SLOPPY,
RelocInfo::kNoPosition);
- cache = EnsureCapacityFor(cache, 1, &key);
+ cache = EnsureCapacity(cache, 1, &key);
Handle<Object> k = key.AsObject(isolate->factory());
int entry = cache->FindInsertionEntry(key.Hash());
cache->set(EntryToIndex(entry), *k);
@@ -15059,7 +15688,7 @@
Isolate* isolate = cache->GetIsolate();
Handle<SharedFunctionInfo> shared(context->closure()->shared());
StringSharedKey key(src, shared, value->strict_mode(), scope_position);
- cache = EnsureCapacityFor(cache, 1, &key);
+ cache = EnsureCapacity(cache, 1, &key);
Handle<Object> k = key.AsObject(isolate->factory());
int entry = cache->FindInsertionEntry(key.Hash());
cache->set(EntryToIndex(entry), *k);
@@ -15073,7 +15702,7 @@
Handle<CompilationCacheTable> cache, Handle<String> src,
JSRegExp::Flags flags, Handle<FixedArray> value) {
RegExpKey key(src, flags);
- cache = EnsureCapacityFor(cache, 1, &key);
+ cache = EnsureCapacity(cache, 1, &key);
int entry = cache->FindInsertionEntry(key.Hash());
// We store the value in the key slot, and compare the search key
// to the stored value with a custon IsMatch function during lookups.
@@ -15084,14 +15713,6 @@
}
-Handle<CompilationCacheTable> CompilationCacheTable::EnsureCapacityFor(
- Handle<CompilationCacheTable> cache, int n, HashTableKey* key) {
- CALL_HEAP_FUNCTION(cache->GetIsolate(),
- cache->EnsureCapacity(n, key),
- CompilationCacheTable);
-}
-
-
void CompilationCacheTable::Remove(Object* value) {
DisallowHeapAllocation no_allocation;
Object* the_hole_value = GetHeap()->the_hole_value();
@@ -15111,7 +15732,7 @@
// StringsKey used for HashTable where key is array of internalized strings.
class StringsKey : public HashTableKey {
public:
- explicit StringsKey(FixedArray* strings) : strings_(strings) { }
+ explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
bool IsMatch(Object* strings) {
FixedArray* o = FixedArray::cast(strings);
@@ -15123,7 +15744,7 @@
return true;
}
- uint32_t Hash() { return HashForObject(strings_); }
+ uint32_t Hash() { return HashForObject(*strings_); }
uint32_t HashForObject(Object* obj) {
FixedArray* strings = FixedArray::cast(obj);
@@ -15135,34 +15756,32 @@
return hash;
}
- Object* AsObject(Heap* heap) { return strings_; }
+ Object* AsObject(Heap* heap) { return *strings_; }
private:
- FixedArray* strings_;
+ Handle<FixedArray> strings_;
};
Object* MapCache::Lookup(FixedArray* array) {
- StringsKey key(array);
+ DisallowHeapAllocation no_alloc;
+ StringsKey key(handle(array));
int entry = FindEntry(&key);
if (entry == kNotFound) return GetHeap()->undefined_value();
return get(EntryToIndex(entry) + 1);
}
-MaybeObject* MapCache::Put(FixedArray* array, Map* value) {
+Handle<MapCache> MapCache::Put(
+ Handle<MapCache> map_cache, Handle<FixedArray> array, Handle<Map> value) {
StringsKey key(array);
- Object* obj;
- { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
- MapCache* cache = reinterpret_cast<MapCache*>(obj);
- int entry = cache->FindInsertionEntry(key.Hash());
- cache->set(EntryToIndex(entry), array);
- cache->set(EntryToIndex(entry) + 1, value);
- cache->ElementAdded();
- return cache;
+ Handle<MapCache> new_cache = EnsureCapacity(map_cache, 1, &key);
+ int entry = new_cache->FindInsertionEntry(key.Hash());
+ new_cache->set(EntryToIndex(entry), *array);
+ new_cache->set(EntryToIndex(entry) + 1, *value);
+ new_cache->ElementAdded();
+ return new_cache;
}
@@ -15187,6 +15806,23 @@
}
+template<typename Derived, typename Shape, typename Key>
+Handle<Derived> Dictionary<Derived, Shape, Key>::New(
+ Isolate* isolate,
+ int at_least_space_for,
+ PretenureFlag pretenure) {
+ Handle<Derived> dict = DerivedHashTable::New(isolate,
+ at_least_space_for,
+ USE_DEFAULT_MINIMUM_CAPACITY,
+ pretenure);
+
+ // Initialize the next enumeration index.
+ dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
+ return dict;
+}
+
+
+
void NameDictionary::DoGenerateNewEnumerationIndices(
Handle<NameDictionary> dictionary) {
CALL_HEAP_FUNCTION_VOID(dictionary->GetIsolate(),
@@ -15267,6 +15903,17 @@
}
+
+template<typename Derived, typename Shape, typename Key>
+Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
+ Handle<Derived> obj, int n, Key key) {
+ Isolate* isolate = obj->GetIsolate();
+ CALL_HEAP_FUNCTION(isolate,
+ obj->EnsureCapacity(n, key),
+ Derived);
+}
+
+
// TODO(ishell): Temporary wrapper until handlified.
template<typename Derived, typename Shape, typename Key>
Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
@@ -15608,20 +16255,6 @@
}
-Handle<ObjectHashTable> ObjectHashTable::EnsureCapacity(
- Handle<ObjectHashTable> table,
- int n,
- Handle<Object> key,
- PretenureFlag pretenure) {
- Handle<HashTable<ObjectHashTable,
- ObjectHashTableShape,
- Object*> > table_base = table;
- CALL_HEAP_FUNCTION(table_base->GetIsolate(),
- table_base->EnsureCapacity(n, *key, pretenure),
- ObjectHashTable);
-}
-
-
Object* ObjectHashTable::Lookup(Object* key) {
ASSERT(IsKey(key));
@@ -15662,7 +16295,7 @@
}
// Check whether the hash table should be extended.
- table = EnsureCapacity(table, 1, key);
+ table = EnsureCapacity(table, 1, *key);
table->AddEntry(table->FindInsertionEntry(Handle<Smi>::cast(hash)->value()),
*key,
*value);
@@ -15719,15 +16352,14 @@
}
-template<class Derived, int entrysize>
-Handle<Derived> OrderedHashTable<Derived, entrysize>::Allocate(
+template<class Derived, class Iterator, int entrysize>
+Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
Isolate* isolate, int capacity, PretenureFlag pretenure) {
// Capacity must be a power of two, since we depend on being able
// to divide and multiple by 2 (kLoadFactor) to derive capacity
// from number of buckets. If we decide to change kLoadFactor
// to something other than 2, capacity should be stored as another
// field of this object.
- const int kMinCapacity = 4;
capacity = RoundUpToPowerOf2(Max(kMinCapacity, capacity));
if (capacity > kMaxCapacity) {
v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
@@ -15744,12 +16376,13 @@
table->SetNumberOfBuckets(num_buckets);
table->SetNumberOfElements(0);
table->SetNumberOfDeletedElements(0);
+ table->set_iterators(isolate->heap()->undefined_value());
return table;
}
-template<class Derived, int entrysize>
-Handle<Derived> OrderedHashTable<Derived, entrysize>::EnsureGrowable(
+template<class Derived, class Iterator, int entrysize>
+Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
Handle<Derived> table) {
int nof = table->NumberOfElements();
int nod = table->NumberOfDeletedElements();
@@ -15762,8 +16395,8 @@
}
-template<class Derived, int entrysize>
-Handle<Derived> OrderedHashTable<Derived, entrysize>::Shrink(
+template<class Derived, class Iterator, int entrysize>
+Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
Handle<Derived> table) {
int nof = table->NumberOfElements();
int capacity = table->Capacity();
@@ -15772,8 +16405,31 @@
}
-template<class Derived, int entrysize>
-Handle<Derived> OrderedHashTable<Derived, entrysize>::Rehash(
+template<class Derived, class Iterator, int entrysize>
+Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
+ Handle<Derived> table) {
+ Handle<Derived> new_table =
+ Allocate(table->GetIsolate(),
+ kMinCapacity,
+ table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
+
+ new_table->set_iterators(table->iterators());
+ table->set_iterators(table->GetHeap()->undefined_value());
+
+ DisallowHeapAllocation no_allocation;
+ for (Object* object = new_table->iterators();
+ !object->IsUndefined();
+ object = Iterator::cast(object)->next_iterator()) {
+ Iterator::cast(object)->TableCleared();
+ Iterator::cast(object)->set_table(*new_table);
+ }
+
+ return new_table;
+}
+
+
+template<class Derived, class Iterator, int entrysize>
+Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
Handle<Derived> table, int new_capacity) {
Handle<Derived> new_table =
Allocate(table->GetIsolate(),
@@ -15800,12 +16456,24 @@
++new_entry;
}
new_table->SetNumberOfElements(nof);
+
+ new_table->set_iterators(table->iterators());
+ table->set_iterators(table->GetHeap()->undefined_value());
+
+ DisallowHeapAllocation no_allocation;
+ for (Object* object = new_table->iterators();
+ !object->IsUndefined();
+ object = Iterator::cast(object)->next_iterator()) {
+ Iterator::cast(object)->TableCompacted();
+ Iterator::cast(object)->set_table(*new_table);
+ }
+
return new_table;
}
-template<class Derived, int entrysize>
-int OrderedHashTable<Derived, entrysize>::FindEntry(Object* key) {
+template<class Derived, class Iterator, int entrysize>
+int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(Object* key) {
ASSERT(!key->IsTheHole());
Object* hash = key->GetHash();
if (hash->IsUndefined()) return kNotFound;
@@ -15820,9 +16488,9 @@
}
-template<class Derived, int entrysize>
-int OrderedHashTable<Derived, entrysize>::AddEntry(int hash) {
- int entry = NumberOfElements() + NumberOfDeletedElements();
+template<class Derived, class Iterator, int entrysize>
+int OrderedHashTable<Derived, Iterator, entrysize>::AddEntry(int hash) {
+ int entry = UsedCapacity();
int bucket = HashToBucket(hash);
int index = EntryToIndex(entry);
Object* chain_entry = get(kHashTableStartIndex + bucket);
@@ -15833,19 +16501,74 @@
}
-template<class Derived, int entrysize>
-void OrderedHashTable<Derived, entrysize>::RemoveEntry(int entry) {
+template<class Derived, class Iterator, int entrysize>
+void OrderedHashTable<Derived, Iterator, entrysize>::RemoveEntry(int entry) {
int index = EntryToIndex(entry);
for (int i = 0; i < entrysize; ++i) {
set_the_hole(index + i);
}
SetNumberOfElements(NumberOfElements() - 1);
SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
+
+ DisallowHeapAllocation no_allocation;
+ for (Object* object = iterators();
+ !object->IsUndefined();
+ object = Iterator::cast(object)->next_iterator()) {
+ Iterator::cast(object)->EntryRemoved(entry);
+ }
}
-template class OrderedHashTable<OrderedHashSet, 1>;
-template class OrderedHashTable<OrderedHashMap, 2>;
+template Handle<OrderedHashSet>
+OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
+ Isolate* isolate, int capacity, PretenureFlag pretenure);
+
+template Handle<OrderedHashSet>
+OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
+ Handle<OrderedHashSet> table);
+
+template Handle<OrderedHashSet>
+OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
+ Handle<OrderedHashSet> table);
+
+template Handle<OrderedHashSet>
+OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
+ Handle<OrderedHashSet> table);
+
+template int
+OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::FindEntry(Object* key);
+
+template int
+OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::AddEntry(int hash);
+
+template void
+OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::RemoveEntry(int entry);
+
+
+template Handle<OrderedHashMap>
+OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
+ Isolate* isolate, int capacity, PretenureFlag pretenure);
+
+template Handle<OrderedHashMap>
+OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
+ Handle<OrderedHashMap> table);
+
+template Handle<OrderedHashMap>
+OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
+ Handle<OrderedHashMap> table);
+
+template Handle<OrderedHashMap>
+OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
+ Handle<OrderedHashMap> table);
+
+template int
+OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::FindEntry(Object* key);
+
+template int
+OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::AddEntry(int hash);
+
+template void
+OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::RemoveEntry(int entry);
bool OrderedHashSet::Contains(Object* key) {
@@ -15871,7 +16594,6 @@
int entry = table->FindEntry(*key);
if (entry == kNotFound) return table;
table->RemoveEntry(entry);
- // TODO(adamk): Don't shrink if we're being iterated over
return Shrink(table);
}
@@ -15891,7 +16613,6 @@
if (value->IsTheHole()) {
if (entry == kNotFound) return table;
table->RemoveEntry(entry);
- // TODO(adamk): Only shrink if not iterating
return Shrink(table);
}
@@ -15910,6 +16631,221 @@
}
+template<class Derived, class TableType>
+void OrderedHashTableIterator<Derived, TableType>::EntryRemoved(int index) {
+ int i = this->index()->value();
+ if (index < i) {
+ set_count(Smi::FromInt(count()->value() - 1));
+ }
+ if (index == i) {
+ Seek();
+ }
+}
+
+
+template<class Derived, class TableType>
+void OrderedHashTableIterator<Derived, TableType>::Close() {
+ if (Closed()) return;
+
+ DisallowHeapAllocation no_allocation;
+
+ Object* undefined = GetHeap()->undefined_value();
+ TableType* table = TableType::cast(this->table());
+ Object* previous = previous_iterator();
+ Object* next = next_iterator();
+
+ if (previous == undefined) {
+ ASSERT_EQ(table->iterators(), this);
+ table->set_iterators(next);
+ } else {
+ ASSERT_EQ(Derived::cast(previous)->next_iterator(), this);
+ Derived::cast(previous)->set_next_iterator(next);
+ }
+
+ if (!next->IsUndefined()) {
+ ASSERT_EQ(Derived::cast(next)->previous_iterator(), this);
+ Derived::cast(next)->set_previous_iterator(previous);
+ }
+
+ set_previous_iterator(undefined);
+ set_next_iterator(undefined);
+ set_table(undefined);
+}
+
+
+template<class Derived, class TableType>
+void OrderedHashTableIterator<Derived, TableType>::Seek() {
+ ASSERT(!Closed());
+
+ DisallowHeapAllocation no_allocation;
+
+ int index = this->index()->value();
+
+ TableType* table = TableType::cast(this->table());
+ int used_capacity = table->UsedCapacity();
+
+ while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
+ index++;
+ }
+ set_index(Smi::FromInt(index));
+}
+
+
+template<class Derived, class TableType>
+void OrderedHashTableIterator<Derived, TableType>::MoveNext() {
+ ASSERT(!Closed());
+
+ set_index(Smi::FromInt(index()->value() + 1));
+ set_count(Smi::FromInt(count()->value() + 1));
+ Seek();
+}
+
+
+template<class Derived, class TableType>
+Handle<JSObject> OrderedHashTableIterator<Derived, TableType>::Next(
+ Handle<Derived> iterator) {
+ Isolate* isolate = iterator->GetIsolate();
+ Factory* factory = isolate->factory();
+
+ Handle<Object> object(iterator->table(), isolate);
+
+ if (!object->IsUndefined()) {
+ Handle<TableType> table = Handle<TableType>::cast(object);
+ int index = iterator->index()->value();
+ if (index < table->UsedCapacity()) {
+ int entry_index = table->EntryToIndex(index);
+ iterator->MoveNext();
+ Handle<Object> value = Derived::ValueForKind(iterator, entry_index);
+ return factory->NewIteratorResultObject(value, false);
+ } else {
+ iterator->Close();
+ }
+ }
+
+ return factory->NewIteratorResultObject(factory->undefined_value(), true);
+}
+
+
+template<class Derived, class TableType>
+Handle<Derived> OrderedHashTableIterator<Derived, TableType>::CreateInternal(
+ Handle<Map> map,
+ Handle<TableType> table,
+ int kind) {
+ Isolate* isolate = table->GetIsolate();
+
+ Handle<Object> undefined = isolate->factory()->undefined_value();
+
+ Handle<Derived> new_iterator = Handle<Derived>::cast(
+ isolate->factory()->NewJSObjectFromMap(map));
+ new_iterator->set_previous_iterator(*undefined);
+ new_iterator->set_table(*table);
+ new_iterator->set_index(Smi::FromInt(0));
+ new_iterator->set_count(Smi::FromInt(0));
+ new_iterator->set_kind(Smi::FromInt(kind));
+
+ Handle<Object> old_iterator(table->iterators(), isolate);
+ if (!old_iterator->IsUndefined()) {
+ Handle<Derived>::cast(old_iterator)->set_previous_iterator(*new_iterator);
+ new_iterator->set_next_iterator(*old_iterator);
+ } else {
+ new_iterator->set_next_iterator(*undefined);
+ }
+
+ table->set_iterators(*new_iterator);
+
+ return new_iterator;
+}
+
+
+template void
+OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::EntryRemoved(
+ int index);
+
+template void
+OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Close();
+
+template Handle<JSObject>
+OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
+ Handle<JSSetIterator> iterator);
+
+template Handle<JSSetIterator>
+OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CreateInternal(
+ Handle<Map> map, Handle<OrderedHashSet> table, int kind);
+
+
+template void
+OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::EntryRemoved(
+ int index);
+
+template void
+OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Close();
+
+template Handle<JSObject>
+OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
+ Handle<JSMapIterator> iterator);
+
+template Handle<JSMapIterator>
+OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CreateInternal(
+ Handle<Map> map, Handle<OrderedHashMap> table, int kind);
+
+
+Handle<Object> JSSetIterator::ValueForKind(
+ Handle<JSSetIterator> iterator, int entry_index) {
+ int kind = iterator->kind()->value();
+ // Set.prototype only has values and entries.
+ ASSERT(kind == kKindValues || kind == kKindEntries);
+
+ Isolate* isolate = iterator->GetIsolate();
+ Factory* factory = isolate->factory();
+
+ Handle<OrderedHashSet> table(
+ OrderedHashSet::cast(iterator->table()), isolate);
+ Handle<Object> value = Handle<Object>(table->get(entry_index), isolate);
+
+ if (kind == kKindEntries) {
+ Handle<FixedArray> array = factory->NewFixedArray(2);
+ array->set(0, *value);
+ array->set(1, *value);
+ return factory->NewJSArrayWithElements(array);
+ }
+
+ return value;
+}
+
+
+Handle<Object> JSMapIterator::ValueForKind(
+ Handle<JSMapIterator> iterator, int entry_index) {
+ int kind = iterator->kind()->value();
+ ASSERT(kind == kKindKeys || kind == kKindValues || kind == kKindEntries);
+
+ Isolate* isolate = iterator->GetIsolate();
+ Factory* factory = isolate->factory();
+
+ Handle<OrderedHashMap> table(
+ OrderedHashMap::cast(iterator->table()), isolate);
+
+ switch (kind) {
+ case kKindKeys:
+ return Handle<Object>(table->get(entry_index), isolate);
+
+ case kKindValues:
+ return Handle<Object>(table->get(entry_index + 1), isolate);
+
+ case kKindEntries: {
+ Handle<Object> key(table->get(entry_index), isolate);
+ Handle<Object> value(table->get(entry_index + 1), isolate);
+ Handle<FixedArray> array = factory->NewFixedArray(2);
+ array->set(0, *key);
+ array->set(1, *value);
+ return factory->NewJSArrayWithElements(array);
+ }
+ }
+
+ UNREACHABLE();
+ return factory->undefined_value();
+}
+
+
DeclaredAccessorDescriptorIterator::DeclaredAccessorDescriptorIterator(
DeclaredAccessorDescriptor* descriptor)
: array_(descriptor->serialized_data()->GetDataStartAddress()),
@@ -16478,14 +17414,16 @@
}
-void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) {
- Handle<DependentCode> dep(dependent_code());
+// static
+void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell,
+ CompilationInfo* info) {
Handle<DependentCode> codes =
- DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup,
+ DependentCode::Insert(handle(cell->dependent_code(), info->isolate()),
+ DependentCode::kPropertyCellChangedGroup,
info->object_wrapper());
- if (*codes != dependent_code()) set_dependent_code(*codes);
+ if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
- Handle<HeapObject>(this), info->zone());
+ cell, info->zone());
}
diff --git a/src/objects.h b/src/objects.h
index 23893e7..71eeaa2 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -66,6 +66,8 @@
// - JSDataView
// - JSSet
// - JSMap
+// - JSSetIterator
+// - JSMapIterator
// - JSWeakCollection
// - JSWeakMap
// - JSWeakSet
@@ -445,6 +447,8 @@
V(JS_PROXY_TYPE) \
V(JS_SET_TYPE) \
V(JS_MAP_TYPE) \
+ V(JS_SET_ITERATOR_TYPE) \
+ V(JS_MAP_ITERATOR_TYPE) \
V(JS_WEAK_MAP_TYPE) \
V(JS_WEAK_SET_TYPE) \
V(JS_REGEXP_TYPE) \
@@ -793,6 +797,8 @@
JS_DATA_VIEW_TYPE,
JS_SET_TYPE,
JS_MAP_TYPE,
+ JS_SET_ITERATOR_TYPE,
+ JS_MAP_ITERATOR_TYPE,
JS_WEAK_MAP_TYPE,
JS_WEAK_SET_TYPE,
@@ -924,17 +930,11 @@
inline bool IsFailure();
inline bool IsRetryAfterGC();
inline bool IsException();
- INLINE(bool IsTheHole());
- INLINE(bool IsUninitialized());
inline bool ToObject(Object** obj) {
if (IsFailure()) return false;
*obj = reinterpret_cast<Object*>(this);
return true;
}
- inline Failure* ToFailureUnchecked() {
- ASSERT(IsFailure());
- return reinterpret_cast<Failure*>(this);
- }
inline Object* ToObjectUnchecked() {
// TODO(jkummerow): Turn this back into an ASSERT when we can be certain
// that it never fires in Release mode in the wild.
@@ -953,13 +953,6 @@
return true;
}
- template<typename T>
- inline bool ToHandle(Handle<T>* obj, Isolate* isolate) {
- if (IsFailure()) return false;
- *obj = handle(T::cast(reinterpret_cast<Object*>(this)), isolate);
- return true;
- }
-
#ifdef OBJECT_PRINT
// Prints this object with details.
void Print();
@@ -1053,6 +1046,8 @@
V(JSFunctionProxy) \
V(JSSet) \
V(JSMap) \
+ V(JSSetIterator) \
+ V(JSMapIterator) \
V(JSWeakCollection) \
V(JSWeakMap) \
V(JSWeakSet) \
@@ -1455,7 +1450,8 @@
// Oddball testing.
INLINE(bool IsUndefined());
INLINE(bool IsNull());
- INLINE(bool IsTheHole()); // Shadows MaybeObject's implementation.
+ INLINE(bool IsTheHole());
+ INLINE(bool IsException());
INLINE(bool IsUninitialized());
INLINE(bool IsTrue());
INLINE(bool IsFalse());
@@ -1509,8 +1505,11 @@
return true;
}
- inline MaybeObject* AllocateNewStorageFor(Heap* heap,
- Representation representation);
+ Handle<HeapType> OptimalType(Isolate* isolate, Representation representation);
+
+ inline static Handle<Object> NewStorageFor(Isolate* isolate,
+ Handle<Object> object,
+ Representation representation);
// Returns true if the object is of the correct type to be used as a
// implementation of a JSObject's elements.
@@ -1533,7 +1532,6 @@
// Failure is returned otherwise.
static MUST_USE_RESULT inline Handle<Object> ToSmi(Isolate* isolate,
Handle<Object> object);
- MUST_USE_RESULT inline MaybeObject* ToSmi();
void Lookup(Name* name, LookupResult* result);
@@ -1545,7 +1543,10 @@
MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
Handle<Object> object,
Handle<Name> key);
-
+ MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
+ Isolate* isolate,
+ Handle<Object> object,
+ const char* key);
MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
Handle<Object> object,
Handle<Name> key);
@@ -1574,6 +1575,7 @@
// Return the object's prototype (might be Heap::null_value()).
Object* GetPrototype(Isolate* isolate);
+ static Handle<Object> GetPrototype(Isolate* isolate, Handle<Object> object);
Map* GetMarkerMap(Isolate* isolate);
// Returns the permanent hash code associated with this object. May return
@@ -1706,8 +1708,6 @@
// Returns the space that needs to be collected for RetryAfterGC failures.
inline AllocationSpace allocation_space() const;
- inline bool IsInternalError() const;
-
static inline Failure* RetryAfterGC(AllocationSpace space);
static inline Failure* RetryAfterGC(); // NEW_SPACE
static inline Failure* Exception();
@@ -1957,11 +1957,18 @@
// Layout description.
static const int kValueOffset = HeapObject::kHeaderSize;
// IEEE doubles are two 32 bit words. The first is just mantissa, the second
- // is a mixture of sign, exponent and mantissa. Our current platforms are all
- // little endian apart from non-EABI arm which is little endian with big
- // endian floating point word ordering!
+ // is a mixture of sign, exponent and mantissa. The offsets of two 32 bit
+ // words within double numbers are endian dependent and they are set
+ // accordingly.
+#if defined(V8_TARGET_LITTLE_ENDIAN)
static const int kMantissaOffset = kValueOffset;
static const int kExponentOffset = kValueOffset + 4;
+#elif defined(V8_TARGET_BIG_ENDIAN)
+ static const int kMantissaOffset = kValueOffset + 4;
+ static const int kExponentOffset = kValueOffset;
+#else
+#error Unknown byte ordering
+#endif
static const int kSize = kValueOffset + kDoubleSize;
static const uint32_t kSignMask = 0x80000000u;
@@ -2112,6 +2119,14 @@
bool search_hidden_prototypes = false);
void Lookup(Name* name, LookupResult* result);
+ enum KeyCollectionType { LOCAL_ONLY, INCLUDE_PROTOS };
+
+ // Computes the enumerable keys for a JSObject. Used for implementing
+ // "for (n in object) { }".
+ MUST_USE_RESULT static MaybeHandle<FixedArray> GetKeys(
+ Handle<JSReceiver> object,
+ KeyCollectionType type);
+
protected:
Smi* GenerateIdentityHash();
@@ -2143,6 +2158,10 @@
// Forward declaration for JSObject::GetOrCreateHiddenPropertiesHashTable.
class ObjectHashTable;
+// Forward declaration for JSObject::Copy.
+class AllocationSite;
+
+
// The JSObject describes real heap allocated JavaScript objects with
// properties.
// Note that the map of JSObject changes during execution to enable inline
@@ -2240,10 +2259,10 @@
static Handle<Object> PrepareElementsForSort(Handle<JSObject> object,
uint32_t limit);
// As PrepareElementsForSort, but only on objects where elements is
- // a dictionary, and it will stay a dictionary.
+ // a dictionary, and it will stay a dictionary. Collates undefined and
+ // unexisting elements below limit from position zero of the elements.
static Handle<Object> PrepareSlowElementsForSort(Handle<JSObject> object,
uint32_t limit);
- MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit);
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithCallback(
Handle<JSObject> object,
@@ -2353,9 +2372,10 @@
// Retrieves an AccessorPair property from the given object. Might return
// undefined if the property doesn't exist or is of a different kind.
- static Handle<Object> GetAccessor(Handle<JSObject> object,
- Handle<Name> name,
- AccessorComponent component);
+ MUST_USE_RESULT static MaybeHandle<Object> GetAccessor(
+ Handle<JSObject> object,
+ Handle<Name> name,
+ AccessorComponent component);
// Defines an AccessorPair property on the given object.
// TODO(mstarzinger): Rename to SetAccessor() and return empty handle on
@@ -2368,8 +2388,9 @@
v8::AccessControl access_control = v8::DEFAULT);
// Defines an AccessorInfo property on the given object.
- static Handle<Object> SetAccessor(Handle<JSObject> object,
- Handle<AccessorInfo> info);
+ MUST_USE_RESULT static MaybeHandle<Object> SetAccessor(
+ Handle<JSObject> object,
+ Handle<AccessorInfo> info);
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithInterceptor(
Handle<JSObject> object,
@@ -2523,6 +2544,15 @@
inline bool HasNamedInterceptor();
inline bool HasIndexedInterceptor();
+ // Computes the enumerable keys from interceptors. Used for debug mirrors and
+ // by JSReceiver::GetKeys.
+ MUST_USE_RESULT static MaybeHandle<JSArray> GetKeysForNamedInterceptor(
+ Handle<JSObject> object,
+ Handle<JSReceiver> receiver);
+ MUST_USE_RESULT static MaybeHandle<JSArray> GetKeysForIndexedInterceptor(
+ Handle<JSObject> object,
+ Handle<JSReceiver> receiver);
+
// Support functions for v8 api (needed for correct interceptor behavior).
static bool HasRealNamedProperty(Handle<JSObject> object,
Handle<Name> key);
@@ -2584,6 +2614,7 @@
static void GeneralizeFieldRepresentation(Handle<JSObject> object,
int modify_index,
Representation new_representation,
+ Handle<HeapType> new_field_type,
StoreMode store_mode);
// Convert the object to use the canonical dictionary
@@ -2604,14 +2635,12 @@
int unused_property_fields);
// Access fast-case object properties at index.
- MUST_USE_RESULT inline MaybeObject* FastPropertyAt(
- Representation representation,
- int index);
static Handle<Object> FastPropertyAt(Handle<JSObject> object,
Representation representation,
int index);
inline Object* RawFastPropertyAt(int index);
inline void FastPropertyAtPut(int index, Object* value);
+ void WriteToField(int descriptor, Object* value);
// Access to in object properties.
inline int GetInObjectPropertyOffset(int index);
@@ -2622,9 +2651,10 @@
= UPDATE_WRITE_BARRIER);
// Set the object's prototype (only JSReceiver and null are allowed values).
- static Handle<Object> SetPrototype(Handle<JSObject> object,
- Handle<Object> value,
- bool skip_hidden_prototypes = false);
+ MUST_USE_RESULT static MaybeHandle<Object> SetPrototype(
+ Handle<JSObject> object,
+ Handle<Object> value,
+ bool skip_hidden_prototypes = false);
// Initializes the body after properties slot, properties slot is
// initialized by set_properties. Fill the pre-allocated fields with
@@ -2639,7 +2669,8 @@
bool ReferencesObject(Object* obj);
// Disalow further properties to be added to the object.
- static Handle<Object> PreventExtensions(Handle<JSObject> object);
+ MUST_USE_RESULT static MaybeHandle<Object> PreventExtensions(
+ Handle<JSObject> object);
// ES5 Object.freeze
MUST_USE_RESULT static MaybeHandle<Object> Freeze(Handle<JSObject> object);
@@ -2653,12 +2684,16 @@
kObjectIsShallowArray = 1
};
+ static Handle<JSObject> Copy(Handle<JSObject> object,
+ Handle<AllocationSite> site);
static Handle<JSObject> Copy(Handle<JSObject> object);
- static Handle<JSObject> DeepCopy(Handle<JSObject> object,
- AllocationSiteUsageContext* site_context,
- DeepCopyHints hints = kNoHints);
- static Handle<JSObject> DeepWalk(Handle<JSObject> object,
- AllocationSiteCreationContext* site_context);
+ MUST_USE_RESULT static MaybeHandle<JSObject> DeepCopy(
+ Handle<JSObject> object,
+ AllocationSiteUsageContext* site_context,
+ DeepCopyHints hints = kNoHints);
+ MUST_USE_RESULT static MaybeHandle<JSObject> DeepWalk(
+ Handle<JSObject> object,
+ AllocationSiteCreationContext* site_context);
static Handle<Object> GetDataProperty(Handle<JSObject> object,
Handle<Name> key);
@@ -2744,7 +2779,7 @@
static const int kInitialMaxFastElementArray = 100000;
static const int kFastPropertiesSoftLimit = 12;
- static const int kMaxFastProperties = 64;
+ static const int kMaxFastProperties = 128;
static const int kMaxInstanceSize = 255 * kPointerSize;
// When extending the backing storage for property values, we increase
// its size by more than the 1 entry necessary, so sequentially adding fields
@@ -2891,18 +2926,6 @@
StoreMode mode = ALLOW_AS_CONSTANT,
TransitionFlag flag = INSERT_TRANSITION);
- // Add a constant function property to a fast-case object.
- // This leaves a CONSTANT_TRANSITION in the old map, and
- // if it is called on a second object with this map, a
- // normal property is added instead, with a map transition.
- // This avoids the creation of many maps with the same constant
- // function, all orphaned.
- static void AddConstantProperty(Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> constant,
- PropertyAttributes attributes,
- TransitionFlag flag);
-
// Add a property to a fast-case object.
static void AddFastProperty(Handle<JSObject> object,
Handle<Name> name,
@@ -2912,6 +2935,10 @@
ValueType value_type,
TransitionFlag flag);
+ static void MigrateToNewProperty(Handle<JSObject> object,
+ Handle<Map> transition,
+ Handle<Object> value);
+
// Add a property to a slow-case object.
static void AddSlowProperty(Handle<JSObject> object,
Handle<Name> name,
@@ -2925,8 +2952,9 @@
static Handle<Object> DeletePropertyPostInterceptor(Handle<JSObject> object,
Handle<Name> name,
DeleteMode mode);
- static Handle<Object> DeletePropertyWithInterceptor(Handle<JSObject> object,
- Handle<Name> name);
+ MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithInterceptor(
+ Handle<JSObject> object,
+ Handle<Name> name);
// Deletes the named property in a normalized object.
static Handle<Object> DeleteNormalizedProperty(Handle<JSObject> object,
@@ -3067,6 +3095,9 @@
MUST_USE_RESULT inline MaybeObject* Copy();
MUST_USE_RESULT MaybeObject* CopySize(int new_length,
PretenureFlag pretenure = NOT_TENURED);
+ static Handle<FixedArray> CopySize(Handle<FixedArray> array,
+ int new_length,
+ PretenureFlag pretenure = NOT_TENURED);
// Add the elements of a JSArray to this FixedArray.
MUST_USE_RESULT static MaybeHandle<FixedArray> AddKeysFromJSArray(
@@ -3155,7 +3186,6 @@
// Setter and getter for elements.
inline double get_scalar(int index);
inline int64_t get_representation(int index);
- MUST_USE_RESULT inline MaybeObject* get(int index);
static inline Handle<Object> get(Handle<FixedDoubleArray> array, int index);
inline void set(int index, double value);
inline void set_the_hole(int index);
@@ -3409,12 +3439,14 @@
inline Name* GetKey(int descriptor_number);
inline Object** GetKeySlot(int descriptor_number);
inline Object* GetValue(int descriptor_number);
+ inline void SetValue(int descriptor_number, Object* value);
inline Object** GetValueSlot(int descriptor_number);
inline Object** GetDescriptorStartSlot(int descriptor_number);
inline Object** GetDescriptorEndSlot(int descriptor_number);
inline PropertyDetails GetDetails(int descriptor_number);
inline PropertyType GetType(int descriptor_number);
inline int GetFieldIndex(int descriptor_number);
+ inline HeapType* GetFieldType(int descriptor_number);
inline Object* GetConstant(int descriptor_number);
inline Object* GetCallbacksObject(int descriptor_number);
inline AccessorDescriptor* GetCallbacks(int descriptor_number);
@@ -3422,7 +3454,6 @@
inline Name* GetSortedKey(int descriptor_number);
inline int GetSortedKeyIndex(int descriptor_number);
inline void SetSortedKey(int pointer, int descriptor_number);
- inline void InitializeRepresentations(Representation representation);
inline void SetRepresentation(int descriptor_number,
Representation representation);
@@ -3842,6 +3873,11 @@
int n,
Key key,
PretenureFlag pretenure = NOT_TENURED);
+ static Handle<Derived> EnsureCapacity(
+ Handle<Derived> table,
+ int n,
+ Key key,
+ PretenureFlag pretenure = NOT_TENURED);
};
@@ -3948,7 +3984,8 @@
public:
// Find cached value for a name key, otherwise return null.
Object* Lookup(FixedArray* key);
- MUST_USE_RESULT MaybeObject* Put(FixedArray* key, Map* value);
+ static Handle<MapCache> Put(
+ Handle<MapCache> map_cache, Handle<FixedArray> key, Handle<Map> value);
static inline MapCache* cast(Object* obj);
private:
@@ -4038,9 +4075,17 @@
int at_least_space_for,
PretenureFlag pretenure = NOT_TENURED);
+ // Creates a new dictionary.
+ static Handle<Derived> New(
+ Isolate* isolate,
+ int at_least_space_for,
+ PretenureFlag pretenure = NOT_TENURED);
+
// Ensure enough space for n additional elements.
MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
+ static Handle<Derived> EnsureCapacity(Handle<Derived> obj, int n, Key key);
+
#ifdef OBJECT_PRINT
void Print(FILE* out = stdout);
#endif
@@ -4251,12 +4296,6 @@
return reinterpret_cast<ObjectHashTable*>(obj);
}
- static Handle<ObjectHashTable> EnsureCapacity(
- Handle<ObjectHashTable> table,
- int n,
- Handle<Object> key,
- PretenureFlag pretenure = NOT_TENURED);
-
// Attempt to shrink hash table after removal of key.
static inline Handle<ObjectHashTable> Shrink(Handle<ObjectHashTable> table,
Handle<Object> key);
@@ -4299,16 +4338,17 @@
// [0]: bucket count
// [1]: element count
// [2]: deleted element count
-// [3..(NumberOfBuckets() - 1)]: "hash table", where each item is an offset
+// [3]: live iterators (doubly-linked list)
+// [4..(NumberOfBuckets() - 1)]: "hash table", where each item is an offset
// into the data table (see below) where the
// first item in this bucket is stored.
-// [3 + NumberOfBuckets()..length]: "data table", an array of length
+// [4 + NumberOfBuckets()..length]: "data table", an array of length
// Capacity() * kEntrySize, where the first entrysize
// items are handled by the derived class and the
// item at kChainOffset is another entry into the
// data table indicating the next entry in this hash
// bucket.
-template<class Derived, int entrysize>
+template<class Derived, class Iterator, int entrysize>
class OrderedHashTable: public FixedArray {
public:
// Returns an OrderedHashTable with a capacity of at least |capacity|.
@@ -4323,6 +4363,10 @@
// if possible.
static Handle<Derived> Shrink(Handle<Derived> table);
+ // Returns a new empty OrderedHashTable and updates all the iterators to
+ // point to the new table.
+ static Handle<Derived> Clear(Handle<Derived> table);
+
// Returns kNotFound if the key isn't present.
int FindEntry(Object* key);
@@ -4334,10 +4378,16 @@
return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
}
+ int UsedCapacity() { return NumberOfElements() + NumberOfDeletedElements(); }
+
int NumberOfBuckets() {
return Smi::cast(get(kNumberOfBucketsIndex))->value();
}
+ Object* iterators() { return get(kIteratorsIndex); }
+
+ void set_iterators(Object* value) { set(kIteratorsIndex, value); }
+
// Returns the index into the data table where the new entry
// should be placed. The table is assumed to have enough space
// for a new entry.
@@ -4352,7 +4402,10 @@
return kHashTableStartIndex + NumberOfBuckets() + (entry * kEntrySize);
}
+ Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
+
static const int kNotFound = -1;
+ static const int kMinCapacity = 4;
private:
static Handle<Derived> Rehash(Handle<Derived> table, int new_capacity);
@@ -4373,8 +4426,6 @@
return NumberOfBuckets() * kLoadFactor;
}
- Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
-
// Returns the next entry for the given entry.
int ChainAt(int entry) {
return Smi::cast(get(EntryToIndex(entry) + kChainOffset))->value();
@@ -4392,7 +4443,8 @@
static const int kNumberOfBucketsIndex = 0;
static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1;
static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1;
- static const int kHashTableStartIndex = kNumberOfDeletedElementsIndex + 1;
+ static const int kIteratorsIndex = kNumberOfDeletedElementsIndex + 1;
+ static const int kHashTableStartIndex = kIteratorsIndex + 1;
static const int kEntrySize = entrysize + 1;
static const int kChainOffset = entrysize;
@@ -4404,7 +4456,11 @@
};
-class OrderedHashSet: public OrderedHashTable<OrderedHashSet, 1> {
+class JSSetIterator;
+
+
+class OrderedHashSet: public OrderedHashTable<
+ OrderedHashSet, JSSetIterator, 1> {
public:
static OrderedHashSet* cast(Object* obj) {
ASSERT(obj->IsOrderedHashTable());
@@ -4419,7 +4475,11 @@
};
-class OrderedHashMap: public OrderedHashTable<OrderedHashMap, 2> {
+class JSMapIterator;
+
+
+class OrderedHashMap:public OrderedHashTable<
+ OrderedHashMap, JSMapIterator, 2> {
public:
static OrderedHashMap* cast(Object* obj) {
ASSERT(obj->IsOrderedHashTable());
@@ -4603,6 +4663,10 @@
// Return the initialization flag of the given context local.
InitializationFlag ContextLocalInitFlag(int var);
+ // Return true if this local was introduced by the compiler, and should not be
+ // exposed to the user in a debugger.
+ bool LocalIsSynthetic(int var);
+
// Lookup support for serialized scope info. Returns the
// the stack slot index for a given slot name if the slot is
// present; otherwise returns a value < 0. The name must be an internalized
@@ -4908,15 +4972,12 @@
// Setter and getter.
inline uint8_t get_scalar(int index);
- MUST_USE_RESULT inline Object* get(int index);
static inline Handle<Object> get(Handle<ExternalUint8ClampedArray> array,
int index);
inline void set(int index, uint8_t value);
- // This accessor applies the correct conversion from Smi, HeapNumber and
- // undefined and clamps the converted value between 0 and 255.
- Object* SetValue(uint32_t index, Object* value);
-
+ // This accessor applies the correct conversion from Smi, HeapNumber
+ // and undefined and clamps the converted value between 0 and 255.
static Handle<Object> SetValue(Handle<ExternalUint8ClampedArray> array,
uint32_t index,
Handle<Object> value);
@@ -4937,18 +4998,15 @@
public:
// Setter and getter.
inline int8_t get_scalar(int index);
- MUST_USE_RESULT inline Object* get(int index);
static inline Handle<Object> get(Handle<ExternalInt8Array> array, int index);
inline void set(int index, int8_t value);
+ // This accessor applies the correct conversion from Smi, HeapNumber
+ // and undefined.
static Handle<Object> SetValue(Handle<ExternalInt8Array> array,
uint32_t index,
Handle<Object> value);
- // This accessor applies the correct conversion from Smi, HeapNumber
- // and undefined.
- MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
-
// Casting.
static inline ExternalInt8Array* cast(Object* obj);
@@ -4965,18 +5023,15 @@
public:
// Setter and getter.
inline uint8_t get_scalar(int index);
- MUST_USE_RESULT inline Object* get(int index);
static inline Handle<Object> get(Handle<ExternalUint8Array> array, int index);
inline void set(int index, uint8_t value);
+ // This accessor applies the correct conversion from Smi, HeapNumber
+ // and undefined.
static Handle<Object> SetValue(Handle<ExternalUint8Array> array,
uint32_t index,
Handle<Object> value);
- // This accessor applies the correct conversion from Smi, HeapNumber
- // and undefined.
- MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
-
// Casting.
static inline ExternalUint8Array* cast(Object* obj);
@@ -4993,18 +5048,15 @@
public:
// Setter and getter.
inline int16_t get_scalar(int index);
- MUST_USE_RESULT inline Object* get(int index);
static inline Handle<Object> get(Handle<ExternalInt16Array> array, int index);
inline void set(int index, int16_t value);
+ // This accessor applies the correct conversion from Smi, HeapNumber
+ // and undefined.
static Handle<Object> SetValue(Handle<ExternalInt16Array> array,
uint32_t index,
Handle<Object> value);
- // This accessor applies the correct conversion from Smi, HeapNumber
- // and undefined.
- MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
-
// Casting.
static inline ExternalInt16Array* cast(Object* obj);
@@ -5021,19 +5073,16 @@
public:
// Setter and getter.
inline uint16_t get_scalar(int index);
- MUST_USE_RESULT inline Object* get(int index);
static inline Handle<Object> get(Handle<ExternalUint16Array> array,
int index);
inline void set(int index, uint16_t value);
+ // This accessor applies the correct conversion from Smi, HeapNumber
+ // and undefined.
static Handle<Object> SetValue(Handle<ExternalUint16Array> array,
uint32_t index,
Handle<Object> value);
- // This accessor applies the correct conversion from Smi, HeapNumber
- // and undefined.
- MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
-
// Casting.
static inline ExternalUint16Array* cast(Object* obj);
@@ -5050,18 +5099,15 @@
public:
// Setter and getter.
inline int32_t get_scalar(int index);
- MUST_USE_RESULT inline MaybeObject* get(int index);
static inline Handle<Object> get(Handle<ExternalInt32Array> array, int index);
inline void set(int index, int32_t value);
+ // This accessor applies the correct conversion from Smi, HeapNumber
+ // and undefined.
static Handle<Object> SetValue(Handle<ExternalInt32Array> array,
uint32_t index,
Handle<Object> value);
- // This accessor applies the correct conversion from Smi, HeapNumber
- // and undefined.
- MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
-
// Casting.
static inline ExternalInt32Array* cast(Object* obj);
@@ -5078,19 +5124,16 @@
public:
// Setter and getter.
inline uint32_t get_scalar(int index);
- MUST_USE_RESULT inline MaybeObject* get(int index);
static inline Handle<Object> get(Handle<ExternalUint32Array> array,
int index);
inline void set(int index, uint32_t value);
+ // This accessor applies the correct conversion from Smi, HeapNumber
+ // and undefined.
static Handle<Object> SetValue(Handle<ExternalUint32Array> array,
uint32_t index,
Handle<Object> value);
- // This accessor applies the correct conversion from Smi, HeapNumber
- // and undefined.
- MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
-
// Casting.
static inline ExternalUint32Array* cast(Object* obj);
@@ -5107,19 +5150,16 @@
public:
// Setter and getter.
inline float get_scalar(int index);
- MUST_USE_RESULT inline MaybeObject* get(int index);
static inline Handle<Object> get(Handle<ExternalFloat32Array> array,
int index);
inline void set(int index, float value);
+ // This accessor applies the correct conversion from Smi, HeapNumber
+ // and undefined.
static Handle<Object> SetValue(Handle<ExternalFloat32Array> array,
uint32_t index,
Handle<Object> value);
- // This accessor applies the correct conversion from Smi, HeapNumber
- // and undefined.
- MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
-
// Casting.
static inline ExternalFloat32Array* cast(Object* obj);
@@ -5136,19 +5176,16 @@
public:
// Setter and getter.
inline double get_scalar(int index);
- MUST_USE_RESULT inline MaybeObject* get(int index);
static inline Handle<Object> get(Handle<ExternalFloat64Array> array,
int index);
inline void set(int index, double value);
+ // This accessor applies the correct conversion from Smi, HeapNumber
+ // and undefined.
static Handle<Object> SetValue(Handle<ExternalFloat64Array> array,
uint32_t index,
Handle<Object> value);
- // This accessor applies the correct conversion from Smi, HeapNumber
- // and undefined.
- MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
-
// Casting.
static inline ExternalFloat64Array* cast(Object* obj);
@@ -5198,7 +5235,6 @@
}
inline ElementType get_scalar(int index);
- MUST_USE_RESULT inline MaybeObject* get(int index);
static inline Handle<Object> get(Handle<FixedTypedArray> array, int index);
inline void set(int index, ElementType value);
@@ -5207,8 +5243,6 @@
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
- MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
-
static Handle<Object> SetValue(Handle<FixedTypedArray<Traits> > array,
uint32_t index,
Handle<Object> value);
@@ -5226,7 +5260,6 @@
typedef elementType ElementType; \
static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \
static const char* Designator() { return #type " array"; } \
- static inline MaybeObject* ToObject(Heap* heap, elementType scalar); \
static inline Handle<Object> ToHandle(Isolate* isolate, \
elementType scalar); \
static inline elementType defaultValue(); \
@@ -5983,6 +6016,9 @@
// Group of code that depends on global property values in property cells
// not being changed.
kPropertyCellChangedGroup,
+ // Group of code that omit run-time type checks for the field(s) introduced
+ // by this map.
+ kFieldTypeGroup,
// Group of code that depends on tenuring information in AllocationSites
// not being changed.
kAllocationSiteTenuringChangedGroup,
@@ -6245,6 +6281,7 @@
DECL_ACCESSORS(transitions, TransitionArray)
Map* FindRootMap();
+ Map* FindFieldOwner(int descriptor);
inline int GetInObjectPropertyOffset(int index);
@@ -6254,13 +6291,19 @@
int target_number_of_fields,
int target_inobject,
int target_unused);
- static Handle<Map> GeneralizeAllFieldRepresentations(
- Handle<Map> map,
- Representation new_representation);
+ static Handle<Map> GeneralizeAllFieldRepresentations(Handle<Map> map);
+ static Handle<HeapType> GeneralizeFieldType(Handle<HeapType> type1,
+ Handle<HeapType> type2,
+ Isolate* isolate)
+ V8_WARN_UNUSED_RESULT;
+ static void GeneralizeFieldType(Handle<Map> map,
+ int modify_index,
+ Handle<HeapType> new_field_type);
static Handle<Map> GeneralizeRepresentation(
Handle<Map> map,
int modify_index,
Representation new_representation,
+ Handle<HeapType> new_field_type,
StoreMode store_mode);
static Handle<Map> CopyGeneralizeAllRepresentations(
Handle<Map> map,
@@ -6426,20 +6469,6 @@
static Handle<Map> CurrentMapForDeprecatedInternal(Handle<Map> map);
static Handle<Map> CopyDropDescriptors(Handle<Map> map);
- static Handle<Map> CopyReplaceDescriptors(
- Handle<Map> map,
- Handle<DescriptorArray> descriptors,
- TransitionFlag flag,
- Handle<Name> name,
- SimpleTransitionFlag simple_flag = FULL_TRANSITION);
- static Handle<Map> CopyReplaceDescriptors(
- Handle<Map> map,
- Handle<DescriptorArray> descriptors,
- TransitionFlag flag,
- SimpleTransitionFlag simple_flag = FULL_TRANSITION);
- static Handle<Map> CopyAddDescriptor(Handle<Map> map,
- Descriptor* descriptor,
- TransitionFlag flag);
static Handle<Map> CopyInsertDescriptor(Handle<Map> map,
Descriptor* descriptor,
TransitionFlag flag);
@@ -6449,6 +6478,21 @@
int index,
TransitionFlag flag);
+ MUST_USE_RESULT static MaybeHandle<Map> CopyWithField(
+ Handle<Map> map,
+ Handle<Name> name,
+ Handle<HeapType> type,
+ PropertyAttributes attributes,
+ Representation representation,
+ TransitionFlag flag);
+
+ MUST_USE_RESULT static MaybeHandle<Map> CopyWithConstant(
+ Handle<Map> map,
+ Handle<Name> name,
+ Handle<Object> constant,
+ PropertyAttributes attributes,
+ TransitionFlag flag);
+
static Handle<Map> AsElementsKind(Handle<Map> map, ElementsKind kind);
static Handle<Map> CopyAsElementsKind(Handle<Map> map,
@@ -6457,6 +6501,8 @@
static Handle<Map> CopyForObserved(Handle<Map> map);
+ static Handle<Map> CopyForFreeze(Handle<Map> map);
+
static Handle<Map> CopyNormalized(Handle<Map> map,
PropertyNormalizationMode mode,
NormalizedMapSharingMode sharing);
@@ -6496,7 +6542,6 @@
static void UpdateCodeCache(Handle<Map> map,
Handle<Name> name,
Handle<Code> code);
- MUST_USE_RESULT MaybeObject* UpdateCodeCache(Name* name, Code* code);
// Extend the descriptor array of the map with the list of descriptors.
// In case of duplicates, the latest descriptor is used.
@@ -6562,12 +6607,15 @@
inline bool CanOmitMapChecks();
- void AddDependentCompilationInfo(DependentCode::DependencyGroup group,
- CompilationInfo* info);
+ static void AddDependentCompilationInfo(Handle<Map> map,
+ DependentCode::DependencyGroup group,
+ CompilationInfo* info);
- void AddDependentCode(DependentCode::DependencyGroup group,
- Handle<Code> code);
- void AddDependentIC(Handle<Code> stub);
+ static void AddDependentCode(Handle<Map> map,
+ DependentCode::DependencyGroup group,
+ Handle<Code> code);
+ static void AddDependentIC(Handle<Map> map,
+ Handle<Code> stub);
bool IsMapInArrayPrototypeChain();
@@ -6696,6 +6744,15 @@
Handle<Map> map,
int new_descriptor,
Handle<DescriptorArray> descriptors);
+ static Handle<Map> CopyAddDescriptor(Handle<Map> map,
+ Descriptor* descriptor,
+ TransitionFlag flag);
+ static Handle<Map> CopyReplaceDescriptors(
+ Handle<Map> map,
+ Handle<DescriptorArray> descriptors,
+ TransitionFlag flag,
+ MaybeHandle<Name> maybe_name,
+ SimpleTransitionFlag simple_flag = FULL_TRANSITION);
// Zaps the contents of backing data structures. Note that the
// heap verifier (i.e. VerifyMarkingVisitor) relies on zapping of objects
@@ -6712,6 +6769,8 @@
Map* FindUpdatedMap(int verbatim, int length, DescriptorArray* descriptors);
Map* FindLastMatchMap(int verbatim, int length, DescriptorArray* descriptors);
+ void UpdateDescriptor(int descriptor_number, Descriptor* desc);
+
void PrintGeneralization(FILE* file,
const char* reason,
int modify_index,
@@ -6719,7 +6778,9 @@
int descriptors,
bool constant_to_field,
Representation old_representation,
- Representation new_representation);
+ Representation new_representation,
+ HeapType* old_field_type,
+ HeapType* new_field_type);
static inline void SetPrototypeTransitions(
Handle<Map> map,
@@ -6848,6 +6909,22 @@
// resource is accessible. Otherwise, always return true.
inline bool HasValidSource();
+ // Convert code position into column number.
+ static int GetColumnNumber(Handle<Script> script, int code_pos);
+
+ // Convert code position into (zero-based) line number.
+ // The non-handlified version does not allocate, but may be much slower.
+ static int GetLineNumber(Handle<Script> script, int code_pos);
+ int GetLineNumber(int code_pos);
+
+ static Handle<Object> GetNameOrSourceURL(Handle<Script> script);
+
+ // Init line_ends array with code positions of line ends inside script source.
+ static void InitLineEnds(Handle<Script> script);
+
+ // Get the JS object wrapping the given script; create it if none exists.
+ static Handle<JSObject> GetWrapper(Handle<Script> script);
+
// Dispatched behavior.
DECLARE_PRINTER(Script)
DECLARE_VERIFIER(Script)
@@ -6869,6 +6946,8 @@
static const int kSize = kFlagsOffset + kPointerSize;
private:
+ int GetLineNumberWithArray(int code_pos);
+
// Bit positions in the flags field.
static const int kCompilationTypeBit = 0;
static const int kCompilationStateBit = 1;
@@ -7165,6 +7244,7 @@
inline void set_ast_node_count(int count);
inline int profiler_ticks();
+ inline void set_profiler_ticks(int ticks);
// Inline cache age is used to infer whether the function survived a context
// disposal or not. In the former case we reset the opt_count.
@@ -7338,14 +7418,10 @@
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
static const int kInitialMapOffset =
kInferredNameOffset + kPointerSize;
- // ast_node_count is a Smi field. It could be grouped with another Smi field
- // into a PSEUDO_SMI_ACCESSORS pair (on x64), if one becomes available.
- static const int kAstNodeCountOffset =
- kInitialMapOffset + kPointerSize;
#if V8_HOST_ARCH_32_BIT
// Smi fields.
static const int kLengthOffset =
- kAstNodeCountOffset + kPointerSize;
+ kInitialMapOffset + kPointerSize;
static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
static const int kExpectedNofPropertiesOffset =
kFormalParameterCountOffset + kPointerSize;
@@ -7363,9 +7439,13 @@
kCompilerHintsOffset + kPointerSize;
static const int kCountersOffset =
kOptCountAndBailoutReasonOffset + kPointerSize;
+ static const int kAstNodeCountOffset =
+ kCountersOffset + kPointerSize;
+ static const int kProfilerTicksOffset =
+ kAstNodeCountOffset + kPointerSize;
// Total size.
- static const int kSize = kCountersOffset + kPointerSize;
+ static const int kSize = kProfilerTicksOffset + kPointerSize;
#else
// The only reason to use smi fields instead of int fields
// is to allow iteration without maps decoding during
@@ -7377,7 +7457,7 @@
// word is not set and thus this word cannot be treated as pointer
// to HeapObject during old space traversal.
static const int kLengthOffset =
- kAstNodeCountOffset + kPointerSize;
+ kInitialMapOffset + kPointerSize;
static const int kFormalParameterCountOffset =
kLengthOffset + kIntSize;
@@ -7398,21 +7478,25 @@
static const int kOptCountAndBailoutReasonOffset =
kCompilerHintsOffset + kIntSize;
-
static const int kCountersOffset =
kOptCountAndBailoutReasonOffset + kIntSize;
+ static const int kAstNodeCountOffset =
+ kCountersOffset + kIntSize;
+ static const int kProfilerTicksOffset =
+ kAstNodeCountOffset + kIntSize;
+
// Total size.
- static const int kSize = kCountersOffset + kIntSize;
+ static const int kSize = kProfilerTicksOffset + kIntSize;
#endif
// The construction counter for inobject slack tracking is stored in the
// most significant byte of compiler_hints which is otherwise unused.
// Its offset depends on the endian-ness of the architecture.
-#if __BYTE_ORDER == __LITTLE_ENDIAN
+#if defined(V8_TARGET_LITTLE_ENDIAN)
static const int kConstructionCountOffset = kCompilerHintsOffset + 3;
-#elif __BYTE_ORDER == __BIG_ENDIAN
+#elif defined(V8_TARGET_BIG_ENDIAN)
static const int kConstructionCountOffset = kCompilerHintsOffset + 0;
#else
#error Unknown byte ordering
@@ -7486,12 +7570,12 @@
static const int kNativeBitWithinByte =
(kNative + kCompilerHintsSmiTagSize) % kBitsPerByte;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
+#if defined(V8_TARGET_LITTLE_ENDIAN)
static const int kStrictModeByteOffset = kCompilerHintsOffset +
(kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
static const int kNativeByteOffset = kCompilerHintsOffset +
(kNative + kCompilerHintsSmiTagSize) / kBitsPerByte;
-#elif __BYTE_ORDER == __BIG_ENDIAN
+#elif defined(V8_TARGET_BIG_ENDIAN)
static const int kStrictModeByteOffset = kCompilerHintsOffset +
(kCompilerHintsSize - 1) -
((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
@@ -7559,7 +7643,7 @@
enum ResumeMode { NEXT, THROW };
// Yielding from a generator returns an object with the following inobject
- // properties. See Context::generator_result_map() for the map.
+ // properties. See Context::iterator_result_map() for the map.
static const int kResultValuePropertyIndex = 0;
static const int kResultDonePropertyIndex = 1;
static const int kResultPropertyCount = 2;
@@ -8248,8 +8332,6 @@
static Handle<CompilationCacheTable> PutRegExp(
Handle<CompilationCacheTable> cache, Handle<String> src,
JSRegExp::Flags flags, Handle<FixedArray> value);
- static Handle<CompilationCacheTable> EnsureCapacityFor(
- Handle<CompilationCacheTable> cache, int n, HashTableKey* key);
void Remove(Object* value);
static inline CompilationCacheTable* cast(Object* obj);
@@ -8265,7 +8347,8 @@
DECL_ACCESSORS(normal_type_cache, Object)
// Add the code object to the cache.
- MUST_USE_RESULT MaybeObject* Update(Name* name, Code* code);
+ static void Update(
+ Handle<CodeCache> cache, Handle<Name> name, Handle<Code> code);
// Lookup code object in the cache. Returns code object if found and undefined
// if not.
@@ -8292,8 +8375,10 @@
static const int kSize = kNormalTypeCacheOffset + kPointerSize;
private:
- MUST_USE_RESULT MaybeObject* UpdateDefaultCache(Name* name, Code* code);
- MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(Name* name, Code* code);
+ static void UpdateDefaultCache(
+ Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code);
+ static void UpdateNormalTypeCache(
+ Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code);
Object* LookupDefaultCache(Name* name, Code::Flags flags);
Object* LookupNormalTypeCache(Name* name, Code::Flags flags);
@@ -8336,7 +8421,10 @@
HashTableKey*> {
public:
Object* Lookup(Name* name, Code::Flags flags);
- MUST_USE_RESULT MaybeObject* Put(Name* name, Code* code);
+ static Handle<CodeCacheHashTable> Put(
+ Handle<CodeCacheHashTable> table,
+ Handle<Name> name,
+ Handle<Code> code);
int GetIndex(Name* name, Code::Flags flags);
void RemoveByIndex(int index);
@@ -8360,9 +8448,6 @@
Code::Flags flags,
Handle<Code> code);
- MUST_USE_RESULT MaybeObject* Update(MapHandleList* maps,
- Code::Flags flags,
- Code* code);
// Returns an undefined value if the entry is not found.
Handle<Object> Lookup(MapHandleList* maps, Code::Flags flags);
@@ -8388,9 +8473,11 @@
public:
Object* Lookup(MapHandleList* maps, int code_kind);
- MUST_USE_RESULT MaybeObject* Put(MapHandleList* maps,
- int code_kind,
- Code* code);
+ static Handle<PolymorphicCodeCacheHashTable> Put(
+ Handle<PolymorphicCodeCacheHashTable> hash_table,
+ MapHandleList* maps,
+ int code_kind,
+ Handle<Code> code);
static inline PolymorphicCodeCacheHashTable* cast(Object* obj);
@@ -9238,6 +9325,9 @@
return VisitFlat(visitor, string, offset, string->length(), type);
}
+ static Handle<FixedArray> CalculateLineEnds(Handle<String> string,
+ bool include_ending_line);
+
private:
friend class Name;
@@ -9715,10 +9805,11 @@
DECLARE_VERIFIER(Oddball)
// Initialize the fields.
- MUST_USE_RESULT MaybeObject* Initialize(Heap* heap,
- const char* to_string,
- Object* to_number,
- byte kind);
+ static void Initialize(Isolate* isolate,
+ Handle<Oddball> oddball,
+ const char* to_string,
+ Handle<Object> to_number,
+ byte kind);
// Layout description.
static const int kToStringOffset = HeapObject::kHeaderSize;
@@ -9735,6 +9826,7 @@
static const byte kUndefined = 5;
static const byte kUninitialized = 6;
static const byte kOther = 7;
+ static const byte kException = 8;
typedef FixedBodyDescriptor<kToStringOffset,
kToNumberOffset + kPointerSize,
@@ -9806,9 +9898,8 @@
static Handle<HeapType> UpdatedType(Handle<PropertyCell> cell,
Handle<Object> value);
- void AddDependentCompilationInfo(CompilationInfo* info);
-
- void AddDependentCode(Handle<Code> code);
+ static void AddDependentCompilationInfo(Handle<PropertyCell> cell,
+ CompilationInfo* info);
// Casting.
static inline PropertyCell* cast(Object* obj);
@@ -10031,6 +10122,149 @@
};
+// OrderedHashTableIterator is an iterator that iterates over the keys and
+// values of an OrderedHashTable.
+//
+// The hash table has a reference to the iterator and the iterators themselves
+// have references to the [next_iterator] and [previous_iterator], thus creating
+// a double linked list.
+//
+// When the hash table changes the iterators are called to update their [index]
+// and [count]. The hash table calls [EntryRemoved], [TableCompacted] as well
+// as [TableCleared].
+//
+// When an iterator is done it closes itself. It removes itself from the double
+// linked list and it sets its [table] to undefined, no longer keeping the
+// [table] alive.
+template<class Derived, class TableType>
+class OrderedHashTableIterator: public JSObject {
+ public:
+ // [table]: the backing hash table mapping keys to values.
+ DECL_ACCESSORS(table, Object)
+
+ // [index]: The index into the data table.
+ DECL_ACCESSORS(index, Smi)
+
+ // [count]: The logical index into the data table, ignoring the holes.
+ DECL_ACCESSORS(count, Smi)
+
+ // [kind]: The kind of iteration this is. One of the [Kind] enum values.
+ DECL_ACCESSORS(kind, Smi)
+
+ // [next_iterator]: Used as a double linked list for the live iterators.
+ DECL_ACCESSORS(next_iterator, Object)
+
+ // [previous_iterator]: Used as a double linked list for the live iterators.
+ DECL_ACCESSORS(previous_iterator, Object)
+
+#ifdef OBJECT_PRINT
+ void OrderedHashTableIteratorPrint(FILE* out);
+#endif
+
+ static const int kTableOffset = JSObject::kHeaderSize;
+ static const int kIndexOffset = kTableOffset + kPointerSize;
+ static const int kCountOffset = kIndexOffset + kPointerSize;
+ static const int kKindOffset = kCountOffset + kPointerSize;
+ static const int kNextIteratorOffset = kKindOffset + kPointerSize;
+ static const int kPreviousIteratorOffset = kNextIteratorOffset + kPointerSize;
+ static const int kSize = kPreviousIteratorOffset + kPointerSize;
+
+ enum Kind {
+ kKindKeys = 1,
+ kKindValues = 2,
+ kKindEntries = 3
+ };
+
+ // Called by the underlying [table] when an entry is removed.
+ void EntryRemoved(int index);
+
+ // Called by the underlying [table] when it is compacted/rehashed.
+ void TableCompacted() {
+ // All holes have been removed so index is now same as count.
+ set_index(count());
+ }
+
+ // Called by the underlying [table] when it is cleared.
+ void TableCleared() {
+ set_index(Smi::FromInt(0));
+ set_count(Smi::FromInt(0));
+ }
+
+ // Removes the iterator from the double linked list and removes its reference
+ // back to the [table].
+ void Close();
+
+ // Returns an iterator result object: {value: any, done: boolean} and moves
+ // the index to the next valid entry. Closes the iterator if moving past the
+ // end.
+ static Handle<JSObject> Next(Handle<Derived> iterator);
+
+ protected:
+ static Handle<Derived> CreateInternal(
+ Handle<Map> map, Handle<TableType> table, int kind);
+
+ private:
+ // Ensures [index] is not pointing to a hole.
+ void Seek();
+
+ // Moves [index] to next valid entry. Closes the iterator if moving past the
+ // end.
+ void MoveNext();
+
+ bool Closed() {
+ return table()->IsUndefined();
+ }
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(OrderedHashTableIterator);
+};
+
+
+class JSSetIterator: public OrderedHashTableIterator<JSSetIterator,
+ OrderedHashSet> {
+ public:
+ // Creates a new iterator associated with [table].
+ // [kind] needs to be one of the OrderedHashTableIterator Kind enum values.
+ static inline Handle<JSSetIterator> Create(
+ Handle<OrderedHashSet> table, int kind);
+
+ // Dispatched behavior.
+ DECLARE_PRINTER(JSSetIterator)
+ DECLARE_VERIFIER(JSSetIterator)
+
+ // Casting.
+ static inline JSSetIterator* cast(Object* obj);
+
+ static Handle<Object> ValueForKind(
+ Handle<JSSetIterator> iterator, int entry_index);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(JSSetIterator);
+};
+
+
+class JSMapIterator: public OrderedHashTableIterator<JSMapIterator,
+ OrderedHashMap> {
+ public:
+ // Creates a new iterator associated with [table].
+ // [kind] needs to be one of the OrderedHashTableIterator Kind enum values.
+ static inline Handle<JSMapIterator> Create(
+ Handle<OrderedHashMap> table, int kind);
+
+ // Dispatched behavior.
+ DECLARE_PRINTER(JSMapIterator)
+ DECLARE_VERIFIER(JSMapIterator)
+
+ // Casting.
+ static inline JSMapIterator* cast(Object* obj);
+
+ static Handle<Object> ValueForKind(
+ Handle<JSMapIterator> iterator, int entry_index);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(JSMapIterator);
+};
+
+
// Base class for both JSWeakMap and JSWeakSet
class JSWeakCollection: public JSObject {
public:
@@ -10272,9 +10506,6 @@
uint32_t index,
Handle<Object> value);
- MUST_USE_RESULT MaybeObject* JSArrayUpdateLengthFromIndex(uint32_t index,
- Object* value);
-
// 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.
diff --git a/src/parser.cc b/src/parser.cc
index 18d0ebb..c535704 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -683,8 +683,8 @@
Factory* factory = parser_->isolate()->factory();
Handle<FixedArray> elements = factory->NewFixedArray(args.length());
for (int i = 0; i < args.length(); i++) {
- Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
- ASSERT(!arg_string.is_null());
+ Handle<String> arg_string =
+ factory->NewStringFromUtf8(CStrVector(args[i])).ToHandleChecked();
elements->set(i, *arg_string);
}
Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
@@ -3258,9 +3258,6 @@
FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
? FunctionLiteral::kIsParenthesized
: FunctionLiteral::kNotParenthesized;
- FunctionLiteral::IsGeneratorFlag generator = is_generator
- ? FunctionLiteral::kIsGenerator
- : FunctionLiteral::kNotGenerator;
DeferredFeedbackSlotProcessor* slot_processor;
AstProperties ast_properties;
BailoutReason dont_optimize_reason = kNoReason;
@@ -3389,132 +3386,14 @@
parenthesized_function_ = false; // The bit was set for this function only.
if (is_lazily_parsed) {
- int function_block_pos = position();
- FunctionEntry entry;
- if (cached_data_mode_ == CONSUME_CACHED_DATA) {
- // If we have cached data, we use it to skip parsing the function body.
- // The data contains the information we need to construct the lazy
- // function.
- entry = (*cached_data())->GetFunctionEntry(function_block_pos);
- if (entry.is_valid()) {
- if (entry.end_pos() <= function_block_pos) {
- // End position greater than end of stream is safe, and hard
- // to check.
- ReportInvalidCachedData(function_name, CHECK_OK);
- }
- scanner()->SeekForward(entry.end_pos() - 1);
-
- scope->set_end_position(entry.end_pos());
- Expect(Token::RBRACE, CHECK_OK);
- isolate()->counters()->total_preparse_skipped()->Increment(
- scope->end_position() - function_block_pos);
- materialized_literal_count = entry.literal_count();
- expected_property_count = entry.property_count();
- scope_->SetStrictMode(entry.strict_mode());
- } else {
- // This case happens when we have preparse data but it doesn't contain
- // an entry for the function. Fail the compilation.
- ReportInvalidCachedData(function_name, CHECK_OK);
- }
- } else {
- // With no cached data, we partially parse the function, without
- // building an AST. This gathers the data needed to build a lazy
- // function.
- SingletonLogger logger;
- PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger);
- if (result == PreParser::kPreParseStackOverflow) {
- // Propagate stack overflow.
- set_stack_overflow();
- *ok = false;
- return NULL;
- }
- if (logger.has_error()) {
- const char* arg = logger.argument_opt();
- Vector<const char*> args;
- if (arg != NULL) {
- args = Vector<const char*>(&arg, 1);
- }
- ParserTraits::ReportMessageAt(
- Scanner::Location(logger.start(), logger.end()),
- logger.message(), args, logger.is_reference_error());
- *ok = false;
- return NULL;
- }
- scope->set_end_position(logger.end());
- Expect(Token::RBRACE, CHECK_OK);
- isolate()->counters()->total_preparse_skipped()->Increment(
- scope->end_position() - function_block_pos);
- materialized_literal_count = logger.literals();
- expected_property_count = logger.properties();
- scope_->SetStrictMode(logger.strict_mode());
- if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
- ASSERT(log_);
- // Position right after terminal '}'.
- int body_end = scanner()->location().end_pos;
- log_->LogFunction(function_block_pos, body_end,
- materialized_literal_count,
- expected_property_count,
- scope_->strict_mode());
- }
- }
- }
-
- if (!is_lazily_parsed) {
- // Everything inside an eagerly parsed function will be parsed eagerly
- // (see comment above).
- ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
- body = new(zone()) ZoneList<Statement*>(8, zone());
- if (fvar != NULL) {
- VariableProxy* fproxy = scope_->NewUnresolved(
- factory(), function_name, Interface::NewConst());
- fproxy->BindTo(fvar);
- body->Add(factory()->NewExpressionStatement(
- factory()->NewAssignment(fvar_init_op,
- fproxy,
- factory()->NewThisFunction(pos),
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition), zone());
- }
-
- // For generators, allocate and yield an iterator on function entry.
- if (is_generator) {
- ZoneList<Expression*>* arguments =
- new(zone()) ZoneList<Expression*>(0, zone());
- CallRuntime* allocation = factory()->NewCallRuntime(
- isolate()->factory()->empty_string(),
- Runtime::FunctionForId(Runtime::kHiddenCreateJSGeneratorObject),
- arguments, pos);
- VariableProxy* init_proxy = factory()->NewVariableProxy(
- function_state_->generator_object_variable());
- Assignment* assignment = factory()->NewAssignment(
- Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
- VariableProxy* get_proxy = factory()->NewVariableProxy(
- function_state_->generator_object_variable());
- Yield* yield = factory()->NewYield(
- get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
- body->Add(factory()->NewExpressionStatement(
- yield, RelocInfo::kNoPosition), zone());
- }
-
- ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK);
-
- if (is_generator) {
- VariableProxy* get_proxy = factory()->NewVariableProxy(
- function_state_->generator_object_variable());
- Expression *undefined = factory()->NewLiteral(
- isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
- Yield* yield = factory()->NewYield(
- get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition);
- body->Add(factory()->NewExpressionStatement(
- yield, RelocInfo::kNoPosition), zone());
- }
-
+ SkipLazyFunctionBody(function_name, &materialized_literal_count,
+ &expected_property_count, CHECK_OK);
+ } else {
+ body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
+ is_generator, CHECK_OK);
materialized_literal_count = function_state.materialized_literal_count();
expected_property_count = function_state.expected_property_count();
handler_count = function_state.handler_count();
-
- Expect(Token::RBRACE, CHECK_OK);
- scope->set_end_position(scanner()->location().end_pos);
}
// Validate strict mode. We can do this only after parsing the function,
@@ -3558,6 +3437,9 @@
CheckConflictingVarDeclarations(scope, CHECK_OK);
}
+ FunctionLiteral::IsGeneratorFlag generator = is_generator
+ ? FunctionLiteral::kIsGenerator
+ : FunctionLiteral::kNotGenerator;
FunctionLiteral* function_literal =
factory()->NewFunctionLiteral(function_name,
scope,
@@ -3582,7 +3464,149 @@
}
-PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
+void Parser::SkipLazyFunctionBody(Handle<String> function_name,
+ int* materialized_literal_count,
+ int* expected_property_count,
+ bool* ok) {
+ int function_block_pos = position();
+ if (cached_data_mode_ == CONSUME_CACHED_DATA) {
+ // If we have cached data, we use it to skip parsing the function body. The
+ // data contains the information we need to construct the lazy function.
+ FunctionEntry entry =
+ (*cached_data())->GetFunctionEntry(function_block_pos);
+ if (entry.is_valid()) {
+ if (entry.end_pos() <= function_block_pos) {
+ // End position greater than end of stream is safe, and hard to check.
+ ReportInvalidCachedData(function_name, ok);
+ if (!*ok) {
+ return;
+ }
+ }
+ scanner()->SeekForward(entry.end_pos() - 1);
+
+ scope_->set_end_position(entry.end_pos());
+ Expect(Token::RBRACE, ok);
+ if (!*ok) {
+ return;
+ }
+ isolate()->counters()->total_preparse_skipped()->Increment(
+ scope_->end_position() - function_block_pos);
+ *materialized_literal_count = entry.literal_count();
+ *expected_property_count = entry.property_count();
+ scope_->SetStrictMode(entry.strict_mode());
+ } else {
+ // This case happens when we have preparse data but it doesn't contain an
+ // entry for the function. Fail the compilation.
+ ReportInvalidCachedData(function_name, ok);
+ return;
+ }
+ } else {
+ // With no cached data, we partially parse the function, without building an
+ // AST. This gathers the data needed to build a lazy function.
+ SingletonLogger logger;
+ PreParser::PreParseResult result =
+ ParseLazyFunctionBodyWithPreParser(&logger);
+ if (result == PreParser::kPreParseStackOverflow) {
+ // Propagate stack overflow.
+ set_stack_overflow();
+ *ok = false;
+ return;
+ }
+ if (logger.has_error()) {
+ const char* arg = logger.argument_opt();
+ Vector<const char*> args;
+ if (arg != NULL) {
+ args = Vector<const char*>(&arg, 1);
+ }
+ ParserTraits::ReportMessageAt(
+ Scanner::Location(logger.start(), logger.end()),
+ logger.message(), args, logger.is_reference_error());
+ *ok = false;
+ return;
+ }
+ scope_->set_end_position(logger.end());
+ Expect(Token::RBRACE, ok);
+ if (!*ok) {
+ return;
+ }
+ isolate()->counters()->total_preparse_skipped()->Increment(
+ scope_->end_position() - function_block_pos);
+ *materialized_literal_count = logger.literals();
+ *expected_property_count = logger.properties();
+ scope_->SetStrictMode(logger.strict_mode());
+ if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
+ ASSERT(log_);
+ // Position right after terminal '}'.
+ int body_end = scanner()->location().end_pos;
+ log_->LogFunction(function_block_pos, body_end,
+ *materialized_literal_count,
+ *expected_property_count,
+ scope_->strict_mode());
+ }
+ }
+}
+
+
+ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
+ Handle<String> function_name, int pos, Variable* fvar,
+ Token::Value fvar_init_op, bool is_generator, bool* ok) {
+ // Everything inside an eagerly parsed function will be parsed eagerly
+ // (see comment above).
+ ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
+ ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8, zone());
+ if (fvar != NULL) {
+ VariableProxy* fproxy = scope_->NewUnresolved(
+ factory(), function_name, Interface::NewConst());
+ fproxy->BindTo(fvar);
+ body->Add(factory()->NewExpressionStatement(
+ factory()->NewAssignment(fvar_init_op,
+ fproxy,
+ factory()->NewThisFunction(pos),
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition), zone());
+ }
+
+ // For generators, allocate and yield an iterator on function entry.
+ if (is_generator) {
+ ZoneList<Expression*>* arguments =
+ new(zone()) ZoneList<Expression*>(0, zone());
+ CallRuntime* allocation = factory()->NewCallRuntime(
+ isolate()->factory()->empty_string(),
+ Runtime::FunctionForId(Runtime::kHiddenCreateJSGeneratorObject),
+ arguments, pos);
+ VariableProxy* init_proxy = factory()->NewVariableProxy(
+ function_state_->generator_object_variable());
+ Assignment* assignment = factory()->NewAssignment(
+ Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
+ VariableProxy* get_proxy = factory()->NewVariableProxy(
+ function_state_->generator_object_variable());
+ Yield* yield = factory()->NewYield(
+ get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
+ body->Add(factory()->NewExpressionStatement(
+ yield, RelocInfo::kNoPosition), zone());
+ }
+
+ ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK);
+
+ if (is_generator) {
+ VariableProxy* get_proxy = factory()->NewVariableProxy(
+ function_state_->generator_object_variable());
+ Expression *undefined = factory()->NewLiteral(
+ isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
+ Yield* yield = factory()->NewYield(
+ get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition);
+ body->Add(factory()->NewExpressionStatement(
+ yield, RelocInfo::kNoPosition), zone());
+ }
+
+ Expect(Token::RBRACE, CHECK_OK);
+ scope_->set_end_position(scanner()->location().end_pos);
+
+ return body;
+}
+
+
+PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
SingletonLogger* logger) {
HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
ASSERT_EQ(Token::LBRACE, scanner()->current_token());
@@ -3818,8 +3842,8 @@
RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
failed_ = true;
- *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
- ASSERT(!error_->is_null());
+ *error_ = isolate()->factory()->NewStringFromAscii(
+ message, NOT_TENURED).ToHandleChecked();
// Zip to the end to make sure the no more input is read.
current_ = kEndMarker;
next_pos_ = in()->length();
diff --git a/src/parser.h b/src/parser.h
index 01f23f0..216ee66 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -790,8 +790,23 @@
Handle<String> LookupCachedSymbol(int symbol_id);
- PreParser::PreParseResult LazyParseFunctionLiteral(
- SingletonLogger* logger);
+ // Skip over a lazy function, either using cached data if we have it, or
+ // by parsing the function with PreParser. Consumes the ending }.
+ void SkipLazyFunctionBody(Handle<String> function_name,
+ int* materialized_literal_count,
+ int* expected_property_count,
+ bool* ok);
+
+ PreParser::PreParseResult ParseLazyFunctionBodyWithPreParser(
+ SingletonLogger* logger);
+
+ // Consumes the ending }.
+ ZoneList<Statement*>* ParseEagerFunctionBody(Handle<String> function_name,
+ int pos,
+ Variable* fvar,
+ Token::Value fvar_init_op,
+ bool is_generator,
+ bool* ok);
Isolate* isolate_;
ZoneList<Handle<String> > symbol_cache_;
diff --git a/src/preparser.h b/src/preparser.h
index de08eb3..ce8df77 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -2047,7 +2047,7 @@
Consume(Token::FUNCTION);
int function_token_position = position();
bool is_generator = allow_generators() && Check(Token::MUL);
- IdentifierT name;
+ IdentifierT name = this->EmptyIdentifier();
bool is_strict_reserved_name = false;
Scanner::Location function_name_location = Scanner::Location::invalid();
FunctionLiteral::FunctionType function_type =
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 6bd446e..ae37648 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -355,8 +355,7 @@
CpuProfile::CpuProfile(const char* title, bool record_samples)
: title_(title),
record_samples_(record_samples),
- start_time_(Time::NowFromSystemTime()) {
- timer_.Start();
+ start_time_(TimeTicks::HighResolutionNow()) {
}
@@ -367,7 +366,7 @@
void CpuProfile::CalculateTotalTicksAndSamplingRate() {
- end_time_ = start_time_ + timer_.Elapsed();
+ end_time_ = TimeTicks::HighResolutionNow();
}
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 81980bf..1f23ee2 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -208,8 +208,8 @@
int samples_count() const { return samples_.length(); }
ProfileNode* sample(int index) const { return samples_.at(index); }
- Time start_time() const { return start_time_; }
- Time end_time() const { return end_time_; }
+ TimeTicks start_time() const { return start_time_; }
+ TimeTicks end_time() const { return end_time_; }
void UpdateTicksScale();
@@ -218,9 +218,8 @@
private:
const char* title_;
bool record_samples_;
- Time start_time_;
- Time end_time_;
- ElapsedTimer timer_;
+ TimeTicks start_time_;
+ TimeTicks end_time_;
List<ProfileNode*> samples_;
ProfileTree top_down_;
diff --git a/src/property.cc b/src/property.cc
index 406caec..e7d0c4e 100644
--- a/src/property.cc
+++ b/src/property.cc
@@ -30,60 +30,41 @@
PrintF(out, " -cacheable = %s\n", IsCacheable() ? "true" : "false");
PrintF(out, " -attributes = %x\n", GetAttributes());
if (IsTransition()) {
- switch (type()) {
- case FIELD:
- PrintF(out, " -type = map transition\n");
- PrintF(out, " -map:\n");
- GetTransitionTarget()->Print(out);
- PrintF(out, "\n");
- break;
- case CONSTANT:
- PrintF(out, " -type = constant property transition\n");
- PrintF(out, " -map:\n");
- GetTransitionTarget()->Print(out);
- PrintF(out, "\n");
- break;
- case CALLBACKS:
- PrintF(out, " -type = callbacks transition\n");
- PrintF(out, " -callback object:\n");
- GetCallbackObject()->Print(out);
- break;
- default:
- UNREACHABLE();
- break;
- }
- } else {
- switch (type()) {
- case NORMAL:
- PrintF(out, " -type = normal\n");
- PrintF(out, " -entry = %d", GetDictionaryEntry());
- break;
- case CONSTANT:
- PrintF(out, " -type = constant\n");
- PrintF(out, " -value:\n");
- GetConstant()->Print(out);
- PrintF(out, "\n");
- break;
- case FIELD:
- PrintF(out, " -type = field\n");
- PrintF(out, " -index = %d", GetFieldIndex().field_index());
- PrintF(out, "\n");
- break;
- case CALLBACKS:
- PrintF(out, " -type = call backs\n");
- PrintF(out, " -callback object:\n");
- GetCallbackObject()->Print(out);
- break;
- case HANDLER:
- PrintF(out, " -type = lookup proxy\n");
- break;
- case INTERCEPTOR:
- PrintF(out, " -type = lookup interceptor\n");
- break;
- case NONEXISTENT:
- UNREACHABLE();
- break;
- }
+ PrintF(out, " -transition target:\n");
+ GetTransitionTarget()->Print(out);
+ PrintF(out, "\n");
+ }
+ switch (type()) {
+ case NORMAL:
+ PrintF(out, " -type = normal\n");
+ PrintF(out, " -entry = %d", GetDictionaryEntry());
+ break;
+ case CONSTANT:
+ PrintF(out, " -type = constant\n");
+ PrintF(out, " -value:\n");
+ GetConstant()->Print(out);
+ PrintF(out, "\n");
+ break;
+ case FIELD:
+ PrintF(out, " -type = field\n");
+ PrintF(out, " -index = %d\n", GetFieldIndex().field_index());
+ PrintF(out, " -field type:\n");
+ GetFieldType()->TypePrint(out);
+ break;
+ case CALLBACKS:
+ PrintF(out, " -type = call backs\n");
+ PrintF(out, " -callback object:\n");
+ GetCallbackObject()->Print(out);
+ break;
+ case HANDLER:
+ PrintF(out, " -type = lookup proxy\n");
+ break;
+ case INTERCEPTOR:
+ PrintF(out, " -type = lookup interceptor\n");
+ break;
+ case NONEXISTENT:
+ UNREACHABLE();
+ break;
}
}
diff --git a/src/property.h b/src/property.h
index 4ddcab0..c82fb82 100644
--- a/src/property.h
+++ b/src/property.h
@@ -7,6 +7,7 @@
#include "isolate.h"
#include "factory.h"
+#include "types.h"
namespace v8 {
namespace internal {
@@ -74,8 +75,15 @@
int field_index,
PropertyAttributes attributes,
Representation representation)
- : Descriptor(key, handle(Smi::FromInt(0), key->GetIsolate()), attributes,
+ : Descriptor(key, HeapType::Any(key->GetIsolate()), attributes,
FIELD, representation, field_index) {}
+ FieldDescriptor(Handle<Name> key,
+ int field_index,
+ Handle<HeapType> field_type,
+ PropertyAttributes attributes,
+ Representation representation)
+ : Descriptor(key, field_type, attributes, FIELD,
+ representation, field_index) { }
};
@@ -177,9 +185,26 @@
number_ = number;
}
- bool CanHoldValue(Handle<Object> value) {
- if (IsNormal()) return true;
- return value->FitsRepresentation(details_.representation());
+ bool CanHoldValue(Handle<Object> value) const {
+ switch (type()) {
+ case NORMAL:
+ return true;
+ case FIELD:
+ return value->FitsRepresentation(representation()) &&
+ GetFieldType()->NowContains(value);
+ case CONSTANT:
+ ASSERT(GetConstant() != *value ||
+ value->FitsRepresentation(representation()));
+ return GetConstant() == *value;
+ case CALLBACKS:
+ case HANDLER:
+ case INTERCEPTOR:
+ return true;
+ case NONEXISTENT:
+ UNREACHABLE();
+ }
+ UNREACHABLE();
+ return true;
}
void TransitionResult(JSObject* holder, Map* target) {
@@ -458,6 +483,33 @@
return map->instance_descriptors()->GetFieldIndex(number_);
}
+ HeapType* GetFieldType() const {
+ ASSERT(type() == FIELD);
+ if (lookup_type_ == DESCRIPTOR_TYPE) {
+ return GetFieldTypeFromMap(holder()->map());
+ }
+ ASSERT(lookup_type_ == TRANSITION_TYPE);
+ return GetFieldTypeFromMap(transition_);
+ }
+
+ HeapType* GetFieldTypeFromMap(Map* map) const {
+ ASSERT(lookup_type_ == DESCRIPTOR_TYPE ||
+ lookup_type_ == TRANSITION_TYPE);
+ ASSERT(number_ < map->NumberOfOwnDescriptors());
+ return map->instance_descriptors()->GetFieldType(number_);
+ }
+
+ Map* GetFieldOwner() const {
+ return GetFieldOwnerFromMap(holder()->map());
+ }
+
+ Map* GetFieldOwnerFromMap(Map* map) const {
+ ASSERT(lookup_type_ == DESCRIPTOR_TYPE ||
+ lookup_type_ == TRANSITION_TYPE);
+ ASSERT(number_ < map->NumberOfOwnDescriptors());
+ return map->FindFieldOwner(number_);
+ }
+
void Iterate(ObjectVisitor* visitor);
private:
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index 5784e4d..0c9b9e2 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -185,6 +185,16 @@
SharedFunctionInfo* shared = function->shared();
Code* shared_code = shared->code();
+ List<JSFunction*> functions(4);
+ frame->GetFunctions(&functions);
+ for (int i = functions.length(); --i >= 0; ) {
+ SharedFunctionInfo* shared_function_info = functions[i]->shared();
+ int ticks = shared_function_info->profiler_ticks();
+ if (ticks < Smi::kMaxValue) {
+ shared_function_info->set_profiler_ticks(ticks + 1);
+ }
+ }
+
if (shared_code->kind() != Code::FUNCTION) continue;
if (function->IsInOptimizationQueue()) continue;
diff --git a/src/runtime.cc b/src/runtime.cc
index 5bcf5a5..c508b4a 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -105,6 +105,12 @@
#define RUNTIME_ASSERT(value) \
if (!(value)) return isolate->ThrowIllegalOperation();
+#define RUNTIME_ASSERT_HANDLIFIED(value, T) \
+ if (!(value)) { \
+ isolate->ThrowIllegalOperation(); \
+ return MaybeHandle<T>(); \
+ }
+
// Cast the given object to a value of the specified type and store
// it in a variable with the given name. If the object is not of the
// expected type call IllegalOperation and return.
@@ -116,6 +122,10 @@
RUNTIME_ASSERT(args[index]->Is##Type()); \
Handle<Type> name = args.at<Type>(index);
+#define CONVERT_NUMBER_ARG_HANDLE_CHECKED(name, index) \
+ RUNTIME_ASSERT(args[index]->IsNumber()); \
+ Handle<Object> name = args.at<Object>(index);
+
// Cast the given object to a boolean and store it in a variable with
// the given name. If the object is not a boolean call IllegalOperation
// and return.
@@ -305,8 +315,7 @@
char arr[100];
Vector<char> buffer(arr, ARRAY_SIZE(arr));
const char* str = DoubleToCString(num, buffer);
- Handle<String> name =
- isolate->factory()->NewStringFromAscii(CStrVector(str));
+ Handle<String> name = isolate->factory()->NewStringFromAsciiChecked(str);
maybe_result = JSObject::SetLocalPropertyIgnoreAttributes(
boilerplate, name, value, NONE,
Object::OPTIMAL_REPRESENTATION, mode);
@@ -473,7 +482,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateObjectLiteral) {
+RUNTIME_FUNCTION(RuntimeHidden_CreateObjectLiteral) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
@@ -483,6 +492,8 @@
bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
+ RUNTIME_ASSERT(literals_index >= 0 && literals_index < literals->length());
+
// Check if boilerplate exists. If not, create it first.
Handle<Object> literal_site(literals->get(literals_index), isolate);
Handle<AllocationSite> site;
@@ -501,8 +512,9 @@
AllocationSiteCreationContext creation_context(isolate);
site = creation_context.EnterNewScope();
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::DeepWalk(boilerplate, &creation_context));
+ RETURN_FAILURE_ON_EXCEPTION(
+ isolate,
+ JSObject::DeepWalk(boilerplate, &creation_context));
creation_context.ExitScope(site, boilerplate);
// Update the functions literal and return the boilerplate.
@@ -515,9 +527,11 @@
AllocationSiteUsageContext usage_context(isolate, site, true);
usage_context.EnterNewScope();
- Handle<Object> copy = JSObject::DeepCopy(boilerplate, &usage_context);
+ MaybeHandle<Object> maybe_copy = JSObject::DeepCopy(
+ boilerplate, &usage_context);
usage_context.ExitScope(site, boilerplate);
- RETURN_IF_EMPTY_HANDLE(isolate, copy);
+ Handle<Object> copy;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, copy, maybe_copy);
return *copy;
}
@@ -555,15 +569,18 @@
}
-static MaybeObject* CreateArrayLiteralImpl(Isolate* isolate,
+static MaybeHandle<JSObject> CreateArrayLiteralImpl(Isolate* isolate,
Handle<FixedArray> literals,
int literals_index,
Handle<FixedArray> elements,
int flags) {
+ RUNTIME_ASSERT_HANDLIFIED(literals_index >= 0 &&
+ literals_index < literals->length(), JSObject);
Handle<AllocationSite> site;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ ASSIGN_RETURN_ON_EXCEPTION(
isolate, site,
- GetLiteralAllocationSite(isolate, literals, literals_index, elements));
+ GetLiteralAllocationSite(isolate, literals, literals_index, elements),
+ JSObject);
bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
@@ -572,15 +589,14 @@
JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
? JSObject::kNoHints
: JSObject::kObjectIsShallowArray;
- Handle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
- hints);
+ MaybeHandle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
+ hints);
usage_context.ExitScope(site, boilerplate);
- RETURN_IF_EMPTY_HANDLE(isolate, copy);
- return *copy;
+ return copy;
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateArrayLiteral) {
+RUNTIME_FUNCTION(RuntimeHidden_CreateArrayLiteral) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
@@ -588,50 +604,52 @@
CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
CONVERT_SMI_ARG_CHECKED(flags, 3);
- return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
- flags);
+ Handle<JSObject> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
+ CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
+ flags));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateArrayLiteralStubBailout) {
+RUNTIME_FUNCTION(RuntimeHidden_CreateArrayLiteralStubBailout) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
CONVERT_SMI_ARG_CHECKED(literals_index, 1);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
- return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
- ArrayLiteral::kShallowElements);
+ Handle<JSObject> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
+ CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
+ ArrayLiteral::kShallowElements));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
+RUNTIME_FUNCTION(Runtime_CreateSymbol) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- Handle<Object> name(args[0], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
- Symbol* symbol;
- MaybeObject* maybe = isolate->heap()->AllocateSymbol();
- if (!maybe->To(&symbol)) return maybe;
+ Handle<Symbol> symbol = isolate->factory()->NewSymbol();
if (name->IsString()) symbol->set_name(*name);
- return symbol;
+ return *symbol;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreatePrivateSymbol) {
+RUNTIME_FUNCTION(Runtime_CreatePrivateSymbol) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- Handle<Object> name(args[0], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
- Symbol* symbol;
- MaybeObject* maybe = isolate->heap()->AllocatePrivateSymbol();
- if (!maybe->To(&symbol)) return maybe;
+ Handle<Symbol> symbol = isolate->factory()->NewPrivateSymbol();
if (name->IsString()) symbol->set_name(*name);
- return symbol;
+ return *symbol;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateGlobalPrivateSymbol) {
+RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
@@ -654,7 +672,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewSymbolWrapper) {
+RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0);
@@ -662,7 +680,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolDescription) {
+RUNTIME_FUNCTION(Runtime_SymbolDescription) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(Symbol, symbol, 0);
@@ -670,14 +688,14 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolRegistry) {
+RUNTIME_FUNCTION(Runtime_SymbolRegistry) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
return *isolate->GetSymbolRegistry();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolIsPrivate) {
+RUNTIME_FUNCTION(Runtime_SymbolIsPrivate) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(Symbol, symbol, 0);
@@ -685,49 +703,47 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_CreateJSProxy) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
- Object* prototype = args[1];
- Object* used_prototype =
- prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
- return isolate->heap()->AllocateJSProxy(handler, used_prototype);
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
+ if (!prototype->IsJSReceiver()) prototype = isolate->factory()->null_value();
+ return *isolate->factory()->NewJSProxy(handler, prototype);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_CreateJSFunctionProxy) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 4);
- CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
- Object* call_trap = args[1];
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, call_trap, 1);
RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
- CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
- Object* prototype = args[3];
- Object* used_prototype =
- prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
- return isolate->heap()->AllocateJSFunctionProxy(
- handler, call_trap, construct_trap, used_prototype);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, construct_trap, 2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 3);
+ if (!prototype->IsJSReceiver()) prototype = isolate->factory()->null_value();
+ return *isolate->factory()->NewJSFunctionProxy(
+ handler, call_trap, construct_trap, prototype);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
+RUNTIME_FUNCTION(Runtime_IsJSProxy) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* obj = args[0];
+ CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSProxy());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
+RUNTIME_FUNCTION(Runtime_IsJSFunctionProxy) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* obj = args[0];
+ CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
+RUNTIME_FUNCTION(Runtime_GetHandler) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
@@ -735,7 +751,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
+RUNTIME_FUNCTION(Runtime_GetCallTrap) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
@@ -743,7 +759,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
+RUNTIME_FUNCTION(Runtime_GetConstructTrap) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
@@ -751,7 +767,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
+RUNTIME_FUNCTION(Runtime_Fix) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
@@ -817,7 +833,7 @@
data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
} else {
data =
- V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
+ V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
}
if (data == NULL) return false;
} else {
@@ -850,41 +866,28 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
+RUNTIME_FUNCTION(Runtime_ArrayBufferInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
- CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1);
- size_t allocated_length;
- if (byteLength->IsSmi()) {
- allocated_length = Smi::cast(*byteLength)->value();
- } else {
- ASSERT(byteLength->IsHeapNumber());
- double value = HeapNumber::cast(*byteLength)->value();
-
- ASSERT(value >= 0);
-
- if (value > std::numeric_limits<size_t>::max()) {
- return isolate->Throw(
- *isolate->factory()->NewRangeError("invalid_array_buffer_length",
- HandleVector<Object>(NULL, 0)));
- }
-
- allocated_length = static_cast<size_t>(value);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1);
+ size_t allocated_length = 0;
+ if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) {
+ return isolate->Throw(
+ *isolate->factory()->NewRangeError("invalid_array_buffer_length",
+ HandleVector<Object>(NULL, 0)));
}
-
if (!Runtime::SetupArrayBufferAllocatingData(isolate,
holder, allocated_length)) {
- return isolate->Throw(*isolate->factory()->
- NewRangeError("invalid_array_buffer_length",
- HandleVector<Object>(NULL, 0)));
+ return isolate->Throw(
+ *isolate->factory()->NewRangeError("invalid_array_buffer_length",
+ HandleVector<Object>(NULL, 0)));
}
-
return *holder;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
+RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
@@ -892,20 +895,21 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
+RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
- CONVERT_DOUBLE_ARG_CHECKED(first, 2);
- size_t start = static_cast<size_t>(first);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2);
+ size_t start = 0;
+ RUNTIME_ASSERT(TryNumberToSize(isolate, *first, &start));
size_t target_length = NumberToSize(isolate, target->byte_length());
if (target_length == 0) return isolate->heap()->undefined_value();
size_t source_byte_length = NumberToSize(isolate, source->byte_length());
- CHECK(start <= source_byte_length);
- CHECK(source_byte_length - start >= target_length);
+ RUNTIME_ASSERT(start <= source_byte_length);
+ RUNTIME_ASSERT(source_byte_length - start >= target_length);
uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
CopyBytes(target_data, source_data + start, target_length);
@@ -913,18 +917,17 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferIsView) {
+RUNTIME_FUNCTION(Runtime_ArrayBufferIsView) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(Object, object, 0);
- return object->IsJSArrayBufferView()
- ? isolate->heap()->true_value()
- : isolate->heap()->false_value();
+ return isolate->heap()->ToBoolean(object->IsJSArrayBufferView());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferNeuter) {
+RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0);
if (array_buffer->backing_store() == NULL) {
CHECK(Smi::FromInt(0) == array_buffer->byte_length());
@@ -964,14 +967,14 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
+RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
CONVERT_SMI_ARG_CHECKED(arrayId, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2);
- CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
- CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset_object, 3);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length_object, 4);
ASSERT(holder->GetInternalFieldCount() ==
v8::ArrayBufferView::kInternalFieldCount);
@@ -990,19 +993,21 @@
&fixed_elements_kind,
&element_size);
+ size_t byte_offset = 0;
+ size_t byte_length = 0;
+ RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset_object, &byte_offset));
+ RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length_object, &byte_length));
+
holder->set_byte_offset(*byte_offset_object);
holder->set_byte_length(*byte_length_object);
- size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
- size_t byte_length = NumberToSize(isolate, *byte_length_object);
-
CHECK_EQ(0, static_cast<int>(byte_length % element_size));
size_t length = byte_length / element_size;
if (length > static_cast<unsigned>(Smi::kMaxValue)) {
- return isolate->Throw(*isolate->factory()->
- NewRangeError("invalid_typed_array_length",
- HandleVector<Object>(NULL, 0)));
+ return isolate->Throw(
+ *isolate->factory()->NewRangeError("invalid_typed_array_length",
+ HandleVector<Object>(NULL, 0)));
}
Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
@@ -1044,7 +1049,7 @@
// initializes backing store using memove.
//
// Returns true if backing store was initialized or false otherwise.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
+RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
@@ -1137,18 +1142,16 @@
buffer->backing_store(),
backing_store + source_byte_offset,
byte_length);
- return *isolate->factory()->true_value();
- } else {
- return *isolate->factory()->false_value();
+ return isolate->heap()->true_value();
}
}
- return *isolate->factory()->false_value();
+ return isolate->heap()->false_value();
}
#define BUFFER_VIEW_GETTER(Type, getter, accessor) \
- RUNTIME_FUNCTION(MaybeObject*, Runtime_##Type##Get##getter) { \
+ RUNTIME_FUNCTION(Runtime_##Type##Get##getter) { \
HandleScope scope(isolate); \
ASSERT(args.length() == 1); \
CONVERT_ARG_HANDLE_CHECKED(JS##Type, holder, 0); \
@@ -1162,7 +1165,7 @@
#undef BUFFER_VIEW_GETTER
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGetBuffer) {
+RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
@@ -1185,8 +1188,9 @@
};
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
+RUNTIME_FUNCTION(Runtime_TypedArraySetFastCases) {
HandleScope scope(isolate);
+ ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, source_obj, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, offset_obj, 2);
@@ -1243,14 +1247,15 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayMaxSizeInHeap) {
+RUNTIME_FUNCTION(Runtime_TypedArrayMaxSizeInHeap) {
+ ASSERT(args.length() == 0);
ASSERT_OBJECT_SIZE(
FLAG_typed_array_max_size_in_heap + FixedTypedArrayBase::kDataOffset);
return Smi::FromInt(FLAG_typed_array_max_size_in_heap);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
+RUNTIME_FUNCTION(Runtime_DataViewInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);
@@ -1396,7 +1401,7 @@
#define DATA_VIEW_GETTER(TypeName, Type, Converter) \
- RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGet##TypeName) { \
+ RUNTIME_FUNCTION(Runtime_DataViewGet##TypeName) { \
HandleScope scope(isolate); \
ASSERT(args.length() == 3); \
CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
@@ -1405,7 +1410,7 @@
Type result; \
if (DataViewGetValue( \
isolate, holder, offset, is_little_endian, &result)) { \
- return isolate->heap()->Converter(result); \
+ return *isolate->factory()->Converter(result); \
} else { \
return isolate->Throw(*isolate->factory()->NewRangeError( \
"invalid_data_view_accessor_offset", \
@@ -1413,14 +1418,14 @@
} \
}
-DATA_VIEW_GETTER(Uint8, uint8_t, NumberFromUint32)
-DATA_VIEW_GETTER(Int8, int8_t, NumberFromInt32)
-DATA_VIEW_GETTER(Uint16, uint16_t, NumberFromUint32)
-DATA_VIEW_GETTER(Int16, int16_t, NumberFromInt32)
-DATA_VIEW_GETTER(Uint32, uint32_t, NumberFromUint32)
-DATA_VIEW_GETTER(Int32, int32_t, NumberFromInt32)
-DATA_VIEW_GETTER(Float32, float, NumberFromDouble)
-DATA_VIEW_GETTER(Float64, double, NumberFromDouble)
+DATA_VIEW_GETTER(Uint8, uint8_t, NewNumberFromUint)
+DATA_VIEW_GETTER(Int8, int8_t, NewNumberFromInt)
+DATA_VIEW_GETTER(Uint16, uint16_t, NewNumberFromUint)
+DATA_VIEW_GETTER(Int16, int16_t, NewNumberFromInt)
+DATA_VIEW_GETTER(Uint32, uint32_t, NewNumberFromUint)
+DATA_VIEW_GETTER(Int32, int32_t, NewNumberFromInt)
+DATA_VIEW_GETTER(Float32, float, NewNumber)
+DATA_VIEW_GETTER(Float64, double, NewNumber)
#undef DATA_VIEW_GETTER
@@ -1478,7 +1483,7 @@
#define DATA_VIEW_SETTER(TypeName, Type) \
- RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewSet##TypeName) { \
+ RUNTIME_FUNCTION(Runtime_DataViewSet##TypeName) { \
HandleScope scope(isolate); \
ASSERT(args.length() == 4); \
CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
@@ -1508,7 +1513,7 @@
#undef DATA_VIEW_SETTER
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
+RUNTIME_FUNCTION(Runtime_SetInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
@@ -1518,11 +1523,11 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
+RUNTIME_FUNCTION(Runtime_SetAdd) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- Handle<Object> key(args[1], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
table = OrderedHashSet::Add(table, key);
holder->set_table(*table);
@@ -1530,21 +1535,21 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
+RUNTIME_FUNCTION(Runtime_SetHas) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- Handle<Object> key(args[1], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
return isolate->heap()->ToBoolean(table->Contains(*key));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
+RUNTIME_FUNCTION(Runtime_SetDelete) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- Handle<Object> key(args[1], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
table = OrderedHashSet::Remove(table, key);
holder->set_table(*table);
@@ -1552,7 +1557,18 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) {
+RUNTIME_FUNCTION(Runtime_SetClear) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
+ Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
+ table = OrderedHashSet::Clear(table);
+ holder->set_table(*table);
+ return isolate->heap()->undefined_value();
+}
+
+
+RUNTIME_FUNCTION(Runtime_SetGetSize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
@@ -1561,7 +1577,36 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
+RUNTIME_FUNCTION(Runtime_SetCreateIterator) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
+ CONVERT_SMI_ARG_CHECKED(kind, 1)
+ ASSERT(kind == JSSetIterator::kKindValues
+ || kind == JSSetIterator::kKindEntries);
+ Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
+ return *JSSetIterator::Create(table, kind);
+}
+
+
+RUNTIME_FUNCTION(Runtime_SetIteratorNext) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
+ return *JSSetIterator::Next(holder);
+}
+
+
+RUNTIME_FUNCTION(Runtime_SetIteratorClose) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
+ holder->Close();
+ return isolate->heap()->undefined_value();
+}
+
+
+RUNTIME_FUNCTION(Runtime_MapInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
@@ -1571,7 +1616,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
+RUNTIME_FUNCTION(Runtime_MapGet) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
@@ -1582,7 +1627,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
+RUNTIME_FUNCTION(Runtime_MapHas) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
@@ -1593,7 +1638,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
+RUNTIME_FUNCTION(Runtime_MapDelete) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
@@ -1607,7 +1652,18 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
+RUNTIME_FUNCTION(Runtime_MapClear) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
+ Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
+ table = OrderedHashMap::Clear(table);
+ holder->set_table(*table);
+ return isolate->heap()->undefined_value();
+}
+
+
+RUNTIME_FUNCTION(Runtime_MapSet) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
@@ -1620,7 +1676,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) {
+RUNTIME_FUNCTION(Runtime_MapGetSize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
@@ -1629,25 +1685,56 @@
}
-static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
+RUNTIME_FUNCTION(Runtime_MapCreateIterator) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
+ CONVERT_SMI_ARG_CHECKED(kind, 1)
+ ASSERT(kind == JSMapIterator::kKindKeys
+ || kind == JSMapIterator::kKindValues
+ || kind == JSMapIterator::kKindEntries);
+ Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
+ return *JSMapIterator::Create(table, kind);
+}
+
+
+RUNTIME_FUNCTION(Runtime_MapIteratorNext) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
+ return *JSMapIterator::Next(holder);
+}
+
+
+RUNTIME_FUNCTION(Runtime_MapIteratorClose) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
+ holder->Close();
+ return isolate->heap()->undefined_value();
+}
+
+
+static Handle<JSWeakCollection> WeakCollectionInitialize(
+ Isolate* isolate,
Handle<JSWeakCollection> weak_collection) {
ASSERT(weak_collection->map()->inobject_properties() == 0);
Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
weak_collection->set_table(*table);
weak_collection->set_next(Smi::FromInt(0));
- return *weak_collection;
+ return weak_collection;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionInitialize) {
+RUNTIME_FUNCTION(Runtime_WeakCollectionInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
- return WeakCollectionInitialize(isolate, weak_collection);
+ return *WeakCollectionInitialize(isolate, weak_collection);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionGet) {
+RUNTIME_FUNCTION(Runtime_WeakCollectionGet) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
@@ -1659,7 +1746,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionHas) {
+RUNTIME_FUNCTION(Runtime_WeakCollectionHas) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
@@ -1671,7 +1758,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionDelete) {
+RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
@@ -1686,12 +1773,12 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionSet) {
+RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
- Handle<Object> value(args[2], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
Handle<ObjectHashTable> table(
ObjectHashTable::cast(weak_collection->table()));
Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
@@ -1700,16 +1787,16 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
+RUNTIME_FUNCTION(Runtime_ClassOf) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* obj = args[0];
+ CONVERT_ARG_CHECKED(Object, obj, 0);
if (!obj->IsJSObject()) return isolate->heap()->null_value();
return JSObject::cast(obj)->class_name();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
+RUNTIME_FUNCTION(Runtime_GetPrototype) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
@@ -1722,28 +1809,28 @@
v8::ACCESS_GET)) {
isolate->ReportFailedAccessCheck(Handle<JSObject>::cast(obj),
v8::ACCESS_GET);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->undefined_value();
}
- obj = handle(obj->GetPrototype(isolate), isolate);
+ obj = Object::GetPrototype(isolate, obj);
} while (obj->IsJSObject() &&
JSObject::cast(*obj)->map()->is_hidden_prototype());
return *obj;
}
-static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
- Object* receiver) {
- Object* current = receiver->GetPrototype(isolate);
+static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
+ Isolate* isolate, Handle<Object> receiver) {
+ Handle<Object> current = Object::GetPrototype(isolate, receiver);
while (current->IsJSObject() &&
- JSObject::cast(current)->map()->is_hidden_prototype()) {
- current = current->GetPrototype(isolate);
+ JSObject::cast(*current)->map()->is_hidden_prototype()) {
+ current = Object::GetPrototype(isolate, current);
}
return current;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
+RUNTIME_FUNCTION(Runtime_SetPrototype) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
@@ -1752,18 +1839,17 @@
!isolate->MayNamedAccess(
obj, isolate->factory()->proto_string(), v8::ACCESS_SET)) {
isolate->ReportFailedAccessCheck(obj, v8::ACCESS_SET);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->undefined_value();
}
if (obj->map()->is_observed()) {
- Handle<Object> old_value(
- GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
+ Handle<Object> old_value = GetPrototypeSkipHiddenPrototypes(isolate, obj);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSObject::SetPrototype(obj, prototype, true));
- Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
-
- Handle<Object> new_value(
- GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
+ Handle<Object> new_value = GetPrototypeSkipHiddenPrototypes(isolate, obj);
if (!new_value->SameValue(*old_value)) {
JSObject::EnqueueChangeRecord(obj, "setPrototype",
isolate->factory()->proto_string(),
@@ -1771,22 +1857,24 @@
}
return *result;
}
- Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSObject::SetPrototype(obj, prototype, true));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
+ HandleScope shs(isolate);
ASSERT(args.length() == 2);
// See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
- Object* O = args[0];
- Object* V = args[1];
+ CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
while (true) {
- Object* prototype = V->GetPrototype(isolate);
+ Handle<Object> prototype = Object::GetPrototype(isolate, V);
if (prototype->IsNull()) return isolate->heap()->false_value();
- if (O == prototype) return isolate->heap()->true_value();
+ if (*O == *prototype) return isolate->heap()->true_value();
V = prototype;
}
}
@@ -1981,7 +2069,7 @@
// [false, value, Writeable, Enumerable, Configurable]
// if args[1] is an accessor on args[0]
// [true, GetFunction, SetFunction, Enumerable, Configurable]
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
+RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
@@ -1993,17 +2081,18 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
+RUNTIME_FUNCTION(Runtime_PreventExtensions) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
- Handle<Object> result = JSObject::PreventExtensions(obj);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, JSObject::PreventExtensions(obj));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
+RUNTIME_FUNCTION(Runtime_IsExtensible) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSObject, obj, 0);
@@ -2017,19 +2106,20 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
+RUNTIME_FUNCTION(Runtime_RegExpCompile) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
- Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, RegExpImpl::Compile(re, pattern, flags));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
+RUNTIME_FUNCTION(Runtime_CreateApiFunction) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
@@ -2037,20 +2127,20 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
+RUNTIME_FUNCTION(Runtime_IsTemplate) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* arg = args[0];
+ CONVERT_ARG_HANDLE_CHECKED(Object, arg, 0);
bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
return isolate->heap()->ToBoolean(result);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
+RUNTIME_FUNCTION(Runtime_GetTemplateField) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(HeapObject, templ, 0);
- CONVERT_SMI_ARG_CHECKED(index, 1)
+ CONVERT_SMI_ARG_CHECKED(index, 1);
int offset = index * kPointerSize + HeapObject::kHeaderSize;
InstanceType type = templ->map()->instance_type();
RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
@@ -2065,7 +2155,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
+RUNTIME_FUNCTION(Runtime_DisableAccessChecks) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
@@ -2085,7 +2175,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
+RUNTIME_FUNCTION(Runtime_EnableAccessChecks) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
@@ -2114,7 +2204,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) {
+RUNTIME_FUNCTION(Runtime_SetAccessorProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 6);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@@ -2135,7 +2225,7 @@
}
-static Failure* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
+static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
HandleScope scope(isolate);
Handle<Object> args[1] = { name };
Handle<Object> error = isolate->factory()->NewTypeError(
@@ -2144,13 +2234,13 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeclareGlobals) {
+RUNTIME_FUNCTION(RuntimeHidden_DeclareGlobals) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
Handle<GlobalObject> global = Handle<GlobalObject>(
isolate->context()->global_object());
- Handle<Context> context = args.at<Context>(0);
+ CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
CONVERT_SMI_ARG_CHECKED(flags, 2);
@@ -2222,7 +2312,7 @@
attr = lookup.GetAttributes();
}
// Define or redefine own property.
- RETURN_IF_EMPTY_HANDLE(isolate,
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
global, name, value, static_cast<PropertyAttributes>(attr)));
} else {
@@ -2240,20 +2330,20 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeclareContextSlot) {
+RUNTIME_FUNCTION(RuntimeHidden_DeclareContextSlot) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
// Declarations are always made in a function or native context. In the
// case of eval code, the context passed is the context of the caller,
// which may be some nested context and not the declaration context.
- RUNTIME_ASSERT(args[0]->IsContext());
- Handle<Context> context(Context::cast(args[0])->declaration_context());
-
- Handle<String> name(String::cast(args[1]));
- PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
+ CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 0);
+ Handle<Context> context(context_arg->declaration_context());
+ CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+ CONVERT_SMI_ARG_CHECKED(mode_arg, 2);
+ PropertyAttributes mode = static_cast<PropertyAttributes>(mode_arg);
RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
- Handle<Object> initial_value(args[3], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 3);
int index;
PropertyAttributes attributes;
@@ -2328,7 +2418,7 @@
}
if (object->IsJSGlobalObject()) {
// Define own property on the global object.
- RETURN_IF_EMPTY_HANDLE(isolate,
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
} else {
RETURN_FAILURE_ON_EXCEPTION(isolate,
@@ -2340,7 +2430,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
+RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
HandleScope scope(isolate);
// args[0] == name
// args[1] == language_mode
@@ -2352,7 +2442,6 @@
bool assign = args.length() == 3;
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
- RUNTIME_ASSERT(args[1]->IsSmi());
CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1);
// According to ECMA-262, section 12.2, page 62, the property must
@@ -2401,14 +2490,14 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_InitializeConstGlobal) {
+RUNTIME_FUNCTION(RuntimeHidden_InitializeConstGlobal) {
SealHandleScope shs(isolate);
// All constants are declared with an initial value. The name
// of the constant is the first argument and the initial value
// is the second.
RUNTIME_ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
- Handle<Object> value = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
// Get the current global object from top.
GlobalObject* global = isolate->context()->global_object();
@@ -2428,7 +2517,7 @@
if (!lookup.IsFound()) {
HandleScope handle_scope(isolate);
Handle<GlobalObject> global(isolate->context()->global_object());
- RETURN_IF_EMPTY_HANDLE(
+ RETURN_FAILURE_ON_EXCEPTION(
isolate,
JSObject::SetLocalPropertyIgnoreAttributes(global, name, value,
attributes));
@@ -2478,18 +2567,16 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_InitializeConstContextSlot) {
+RUNTIME_FUNCTION(RuntimeHidden_InitializeConstContextSlot) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
- Handle<Object> value(args[0], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
ASSERT(!value->IsTheHole());
-
// Initializations are always done in a function or native context.
- RUNTIME_ASSERT(args[1]->IsContext());
- Handle<Context> context(Context::cast(args[1])->declaration_context());
-
- Handle<String> name(String::cast(args[2]));
+ CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
+ Handle<Context> context(context_arg->declaration_context());
+ CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
int index;
PropertyAttributes attributes;
@@ -2576,8 +2663,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*,
- Runtime_OptimizeObjectForAddingMultipleProperties) {
+RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@@ -2589,7 +2675,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_RegExpExec) {
+RUNTIME_FUNCTION(RuntimeHidden_RegExpExec) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
@@ -2601,20 +2687,21 @@
RUNTIME_ASSERT(index >= 0);
RUNTIME_ASSERT(index <= subject->length());
isolate->counters()->regexp_entry_runtime()->Increment();
- Handle<Object> result = RegExpImpl::Exec(regexp,
- subject,
- index,
- last_match_info);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ RegExpImpl::Exec(regexp, subject, index, last_match_info));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_RegExpConstructResult) {
+RUNTIME_FUNCTION(RuntimeHidden_RegExpConstructResult) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 3);
CONVERT_SMI_ARG_CHECKED(size, 0);
RUNTIME_ASSERT(size >= 0 && size <= FixedArray::kMaxLength);
+ CONVERT_ARG_HANDLE_CHECKED(Object, index, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, input, 2);
Handle<FixedArray> elements = isolate->factory()->NewFixedArray(size);
Handle<Map> regexp_map(isolate->native_context()->regexp_result_map());
Handle<JSObject> object =
@@ -2623,13 +2710,13 @@
array->set_elements(*elements);
array->set_length(Smi::FromInt(size));
// Write in-object properties after the length of the array.
- array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
- array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
+ array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, *index);
+ array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, *input);
return *array;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
+RUNTIME_FUNCTION(Runtime_RegExpInitializeObject) {
HandleScope scope(isolate);
ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
@@ -2673,21 +2760,21 @@
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
Handle<Object> zero(Smi::FromInt(0), isolate);
Factory* factory = isolate->factory();
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
- regexp, factory->source_string(), source, final));
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
- regexp, factory->global_string(), global, final));
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
- regexp, factory->ignore_case_string(), ignoreCase, final));
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
- regexp, factory->multiline_string(), multiline, final));
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
- regexp, factory->last_index_string(), zero, writable));
+ JSObject::SetLocalPropertyIgnoreAttributes(
+ regexp, factory->source_string(), source, final).Check();
+ JSObject::SetLocalPropertyIgnoreAttributes(
+ regexp, factory->global_string(), global, final).Check();
+ JSObject::SetLocalPropertyIgnoreAttributes(
+ regexp, factory->ignore_case_string(), ignoreCase, final).Check();
+ JSObject::SetLocalPropertyIgnoreAttributes(
+ regexp, factory->multiline_string(), multiline, final).Check();
+ JSObject::SetLocalPropertyIgnoreAttributes(
+ regexp, factory->last_index_string(), zero, writable).Check();
return *regexp;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
+RUNTIME_FUNCTION(Runtime_FinishArrayPrototypeSetup) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
@@ -2716,7 +2803,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
+RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
@@ -2733,7 +2820,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsSloppyModeFunction) {
+RUNTIME_FUNCTION(Runtime_IsSloppyModeFunction) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
@@ -2752,7 +2839,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
+RUNTIME_FUNCTION(Runtime_GetDefaultReceiver) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
@@ -2781,13 +2868,13 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_MaterializeRegExpLiteral) {
+RUNTIME_FUNCTION(RuntimeHidden_MaterializeRegExpLiteral) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
- int index = args.smi_at(1);
- Handle<String> pattern = args.at<String>(2);
- Handle<String> flags = args.at<String>(3);
+ CONVERT_SMI_ARG_CHECKED(index, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
+ CONVERT_ARG_HANDLE_CHECKED(String, flags, 3);
// Get the RegExp function from the context in the literals array.
// This is the RegExp function from the context in which the
@@ -2807,7 +2894,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
+RUNTIME_FUNCTION(Runtime_FunctionGetName) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -2816,7 +2903,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
+RUNTIME_FUNCTION(Runtime_FunctionSetName) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -2827,7 +2914,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
+RUNTIME_FUNCTION(Runtime_FunctionNameShouldPrintAsAnonymous) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, f, 0);
@@ -2836,7 +2923,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
+RUNTIME_FUNCTION(Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, f, 0);
@@ -2845,7 +2932,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsGenerator) {
+RUNTIME_FUNCTION(Runtime_FunctionIsGenerator) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, f, 0);
@@ -2853,7 +2940,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
+RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -2864,7 +2951,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
+RUNTIME_FUNCTION(Runtime_FunctionGetScript) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -2872,11 +2959,11 @@
Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
if (!script->IsScript()) return isolate->heap()->undefined_value();
- return *GetScriptWrapper(Handle<Script>::cast(script));
+ return *Script::GetWrapper(Handle<Script>::cast(script));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
+RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -2886,7 +2973,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
+RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -2896,7 +2983,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
+RUNTIME_FUNCTION(Runtime_FunctionGetPositionForOffset) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -2910,7 +2997,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
+RUNTIME_FUNCTION(Runtime_FunctionSetInstanceClassName) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -2921,7 +3008,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
+RUNTIME_FUNCTION(Runtime_FunctionSetLength) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -2932,7 +3019,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
+RUNTIME_FUNCTION(Runtime_FunctionSetPrototype) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -2944,7 +3031,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
+RUNTIME_FUNCTION(Runtime_FunctionSetReadOnlyPrototype) {
HandleScope shs(isolate);
RUNTIME_ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -2987,7 +3074,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
+RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -2996,7 +3083,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
+RUNTIME_FUNCTION(Runtime_FunctionIsBuiltin) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -3005,12 +3092,12 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
+RUNTIME_FUNCTION(Runtime_SetCode) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
- Handle<Object> code = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, code, 1);
if (code->IsNull()) return *target;
RUNTIME_ASSERT(code->IsJSFunction());
@@ -3019,7 +3106,7 @@
Handle<SharedFunctionInfo> source_shared(source->shared());
if (!Compiler::EnsureCompiled(source, KEEP_EXCEPTION)) {
- return Failure::Exception();
+ return isolate->heap()->exception();
}
// Mark both, the source and the target, as un-flushable because the
@@ -3071,7 +3158,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
+RUNTIME_FUNCTION(Runtime_SetExpectedNumberOfProperties) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
@@ -3094,7 +3181,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateJSGeneratorObject) {
+RUNTIME_FUNCTION(RuntimeHidden_CreateJSGeneratorObject) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
@@ -3120,10 +3207,10 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_SuspendJSGeneratorObject) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_SuspendJSGeneratorObject) {
+ HandleScope handle_scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0);
JavaScriptFrameIterator stack_iterator(isolate);
JavaScriptFrame* frame = stack_iterator.frame();
@@ -3152,11 +3239,10 @@
ASSERT(!frame->HasHandler());
} else {
int stack_handler_index = -1;
- MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count);
- FixedArray* operand_stack;
- if (!alloc->To(&operand_stack)) return alloc;
- frame->SaveOperandStack(operand_stack, &stack_handler_index);
- generator_object->set_operand_stack(operand_stack);
+ Handle<FixedArray> operand_stack =
+ isolate->factory()->NewFixedArray(operands_count);
+ frame->SaveOperandStack(*operand_stack, &stack_handler_index);
+ generator_object->set_operand_stack(*operand_stack);
generator_object->set_stack_handler_index(stack_handler_index);
}
@@ -3171,7 +3257,7 @@
// inlined into GeneratorNext and GeneratorThrow. EmitGeneratorResumeResume is
// called in any case, as it needs to reconstruct the stack frame and make space
// for arguments and operands.
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ResumeJSGeneratorObject) {
+RUNTIME_FUNCTION(RuntimeHidden_ResumeJSGeneratorObject) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
@@ -3219,7 +3305,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowGeneratorStateError) {
+RUNTIME_FUNCTION(RuntimeHidden_ThrowGeneratorStateError) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
@@ -3232,7 +3318,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectFreeze) {
+RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@@ -3242,7 +3328,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCharCodeAt) {
+RUNTIME_FUNCTION(RuntimeHidden_StringCharCodeAt) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
@@ -3262,11 +3348,12 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
+RUNTIME_FUNCTION(Runtime_CharFromCode) {
HandleScope handlescope(isolate);
ASSERT(args.length() == 1);
if (args[0]->IsNumber()) {
- uint32_t code = NumberToUint32(args[0]) & 0xffff;
+ CONVERT_NUMBER_CHECKED(uint32_t, code, Uint32, args[0]);
+ code &= 0xffff;
return *isolate->factory()->LookupSingleCharacterStringFromCode(code);
}
return isolate->heap()->empty_string();
@@ -3917,7 +4004,7 @@
template<typename ResultSeqString>
-MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
+MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString(
Isolate* isolate,
Handle<String> subject,
Handle<JSRegExp> pattern_regexp,
@@ -4005,7 +4092,7 @@
}
-MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
+MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString(
Isolate* isolate,
Handle<String> subject,
Handle<JSRegExp> regexp,
@@ -4037,11 +4124,11 @@
}
RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
int32_t* current_match = global_cache.FetchNext();
if (current_match == NULL) {
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
return *subject;
}
@@ -4083,7 +4170,7 @@
current_match = global_cache.FetchNext();
} while (current_match != NULL);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
if (prev < subject_length) {
builder.EnsureCapacity(2);
@@ -4102,7 +4189,7 @@
template <typename ResultSeqString>
-MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
+MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString(
Isolate* isolate,
Handle<String> subject,
Handle<JSRegExp> regexp,
@@ -4122,11 +4209,11 @@
}
RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
int32_t* current_match = global_cache.FetchNext();
if (current_match == NULL) {
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
return *subject;
}
@@ -4163,7 +4250,7 @@
current_match = global_cache.FetchNext();
} while (current_match != NULL);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
RegExpImpl::SetLastMatchInfo(last_match_info,
subject,
@@ -4200,7 +4287,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
+RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
@@ -4278,7 +4365,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
+RUNTIME_FUNCTION(Runtime_StringReplaceOneCharWithString) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
@@ -4295,7 +4382,7 @@
.ToHandle(&result)) {
return *result;
}
- if (isolate->has_pending_exception()) return Failure::Exception();
+ if (isolate->has_pending_exception()) return isolate->heap()->exception();
subject = String::Flatten(subject);
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
@@ -4358,14 +4445,14 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
+RUNTIME_FUNCTION(Runtime_StringIndexOf) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, index, 2);
- Object* index = args[2];
uint32_t start_index;
if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
@@ -4410,14 +4497,14 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
+RUNTIME_FUNCTION(Runtime_StringLastIndexOf) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, index, 2);
- Object* index = args[2];
uint32_t start_index;
if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
@@ -4469,7 +4556,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
+RUNTIME_FUNCTION(Runtime_StringLocaleCompare) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
@@ -4513,7 +4600,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_SubString) {
+RUNTIME_FUNCTION(RuntimeHidden_SubString) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -4541,16 +4628,16 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
+RUNTIME_FUNCTION(Runtime_StringMatch) {
HandleScope handles(isolate);
- ASSERT_EQ(3, args.length());
+ ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
int capture_count = regexp->CaptureCount();
@@ -4564,7 +4651,7 @@
offsets.Add(match[1], zone_scope.zone()); // end
}
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
if (offsets.length() == 0) {
// Not a single match.
@@ -4598,7 +4685,7 @@
// Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
// separate last match info. See comment on that function.
template<bool has_capture>
-static MaybeObject* SearchRegExpMultiple(
+static Object* SearchRegExpMultiple(
Isolate* isolate,
Handle<String> subject,
Handle<JSRegExp> regexp,
@@ -4636,7 +4723,7 @@
}
RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
Handle<FixedArray> result_elements;
if (result_array->HasFastObjectElements()) {
@@ -4712,7 +4799,7 @@
}
}
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
if (match_start >= 0) {
// Finished matching, with at least one match.
@@ -4733,10 +4820,10 @@
fixed_array->set(fixed_array->length() - 1,
Smi::FromInt(builder.length()));
// Cache the result and turn the FixedArray into a COW array.
- RegExpResultsCache::Enter(isolate->heap(),
- *subject,
- regexp->data(),
- *fixed_array,
+ RegExpResultsCache::Enter(isolate,
+ subject,
+ handle(regexp->data(), isolate),
+ fixed_array,
RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
}
return *builder.ToJSArray(result_array);
@@ -4749,7 +4836,7 @@
// This is only called for StringReplaceGlobalRegExpWithFunction. This sets
// lastMatchInfoOverride to maintain the last match info, so we don't need to
// set any other last match array info.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
+RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) {
HandleScope handles(isolate);
ASSERT(args.length() == 4);
@@ -4771,8 +4858,8 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToRadixString) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(radix, 1);
RUNTIME_ASSERT(2 <= radix && radix <= 36);
@@ -4783,7 +4870,7 @@
if (value >= 0 && value < radix) {
// Character array used for conversion.
static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
- return isolate->heap()->
+ return *isolate->factory()->
LookupSingleCharacterStringFromCode(kCharTable[value]);
}
}
@@ -4791,24 +4878,23 @@
// Slow case.
CONVERT_DOUBLE_ARG_CHECKED(value, 0);
if (std::isnan(value)) {
- return *isolate->factory()->nan_string();
+ return isolate->heap()->nan_string();
}
if (std::isinf(value)) {
if (value < 0) {
- return *isolate->factory()->minus_infinity_string();
+ return isolate->heap()->minus_infinity_string();
}
- return *isolate->factory()->infinity_string();
+ return isolate->heap()->infinity_string();
}
char* str = DoubleToRadixCString(value, radix);
- MaybeObject* result =
- isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
+ Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
DeleteArray(str);
- return result;
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToFixed) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(value, 0);
@@ -4816,15 +4902,14 @@
int f = FastD2IChecked(f_number);
RUNTIME_ASSERT(f >= 0);
char* str = DoubleToFixedCString(value, f);
- MaybeObject* res =
- isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
+ Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
DeleteArray(str);
- return res;
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToExponential) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(value, 0);
@@ -4832,15 +4917,14 @@
int f = FastD2IChecked(f_number);
RUNTIME_ASSERT(f >= -1 && f <= 20);
char* str = DoubleToExponentialCString(value, f);
- MaybeObject* res =
- isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
+ Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
DeleteArray(str);
- return res;
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToPrecision) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(value, 0);
@@ -4848,23 +4932,18 @@
int f = FastD2IChecked(f_number);
RUNTIME_ASSERT(f >= 1 && f <= 21);
char* str = DoubleToPrecisionCString(value, f);
- MaybeObject* res =
- isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
+ Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
DeleteArray(str);
- return res;
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsValidSmi) {
- HandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_IsValidSmi) {
+ SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
- if (Smi::IsValid(number)) {
- return isolate->heap()->true_value();
- } else {
- return isolate->heap()->false_value();
- }
+ return isolate->heap()->ToBoolean(Smi::IsValid(number));
}
@@ -4967,12 +5046,12 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
+RUNTIME_FUNCTION(Runtime_GetProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
- Handle<Object> object = args.at<Object>(0);
- Handle<Object> key = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
@@ -4982,7 +5061,7 @@
// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
+RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -5026,7 +5105,9 @@
if (!result.representation().IsDouble()) {
keyed_lookup_cache->Update(receiver_map, key, offset);
}
- return receiver->FastPropertyAt(result.representation(), offset);
+ HandleScope scope(isolate);
+ return *JSObject::FastPropertyAt(
+ handle(receiver, isolate), result.representation(), offset);
}
} else {
// Attempt dictionary lookup.
@@ -5071,8 +5152,7 @@
Handle<String> str = args.at<String>(0);
int index = args.smi_at(1);
if (index >= 0 && index < str->length()) {
- Handle<Object> result = GetCharAt(str, index);
- return *result;
+ return *GetCharAt(str, index);
}
}
@@ -5098,7 +5178,7 @@
// Steps 9c & 12 - replace an existing data property with an accessor property.
// Step 12 - update an existing accessor property with an accessor or generic
// descriptor.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
+RUNTIME_FUNCTION(Runtime_DefineOrRedefineAccessorProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
@@ -5114,7 +5194,7 @@
bool fast = obj->HasFastProperties();
JSObject::DefineAccessor(obj, name, getter, setter, attr);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
if (fast) JSObject::TransformToFastProperties(obj, 0);
return isolate->heap()->undefined_value();
}
@@ -5126,7 +5206,7 @@
// Steps 9b & 12 - replace an existing accessor property with a data property.
// Step 12 - update an existing data property with a data or generic
// descriptor.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
+RUNTIME_FUNCTION(Runtime_DefineOrRedefineDataProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
@@ -5200,7 +5280,7 @@
// Return property without being observable by accessors or interceptors.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
+RUNTIME_FUNCTION(Runtime_GetDataProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@@ -5222,8 +5302,7 @@
Handle<Object> error =
isolate->factory()->NewTypeError("non_object_property_store",
HandleVector(args, 2));
- isolate->Throw(*error);
- return Handle<Object>();
+ return isolate->Throw<Object>(error);
}
if (object->IsJSProxy()) {
@@ -5394,7 +5473,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHiddenProperty) {
+RUNTIME_FUNCTION(Runtime_SetHiddenProperty) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 3);
@@ -5405,7 +5484,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
+RUNTIME_FUNCTION(Runtime_SetProperty) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
@@ -5434,7 +5513,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
+RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
@@ -5447,7 +5526,7 @@
// Set the native flag on the function.
// This is used to decide if we should transform null and undefined
// into the global object when doing call and apply.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
+RUNTIME_FUNCTION(Runtime_SetNativeFlag) {
SealHandleScope shs(isolate);
RUNTIME_ASSERT(args.length() == 1);
@@ -5461,11 +5540,10 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInlineBuiltinFlag) {
+RUNTIME_FUNCTION(Runtime_SetInlineBuiltinFlag) {
SealHandleScope shs(isolate);
RUNTIME_ASSERT(args.length() == 1);
-
- Handle<Object> object = args.at<Object>(0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
if (object->IsJSFunction()) {
JSFunction* func = JSFunction::cast(*object);
@@ -5475,12 +5553,12 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
+RUNTIME_FUNCTION(Runtime_StoreArrayLiteralElement) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_SMI_ARG_CHECKED(store_index, 1);
- Handle<Object> value = args.at<Object>(2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
CONVERT_SMI_ARG_CHECKED(literal_index, 4);
@@ -5534,18 +5612,17 @@
// Check whether debugger and is about to step into the callback that is passed
// to a built-in function such as Array.forEach.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
+RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) {
SealHandleScope shs(isolate);
#ifdef ENABLE_DEBUGGER_SUPPORT
+ ASSERT(args.length() == 1);
if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) {
return isolate->heap()->false_value();
}
CONVERT_ARG_CHECKED(Object, callback, 0);
// We do not step into the callback if it's a builtin or not even a function.
- if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
- return isolate->heap()->false_value();
- }
- return isolate->heap()->true_value();
+ return isolate->heap()->ToBoolean(
+ callback->IsJSFunction() && !JSFunction::cast(callback)->IsBuiltin());
#else
return isolate->heap()->false_value();
#endif // ENABLE_DEBUGGER_SUPPORT
@@ -5554,9 +5631,10 @@
// Set one shot breakpoints for the callback function that is passed to a
// built-in function such as Array.forEach to enable stepping into the callback.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
+RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
SealHandleScope shs(isolate);
#ifdef ENABLE_DEBUGGER_SUPPORT
+ ASSERT(args.length() == 1);
Debug* debug = isolate->debug();
if (!debug->IsStepping()) return isolate->heap()->undefined_value();
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
@@ -5573,7 +5651,7 @@
// Set a local property, even if it is READ_ONLY. If the property does not
// exist, it will be added with attributes NONE.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
+RUNTIME_FUNCTION(Runtime_IgnoreAttributesAndSetProperty) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@@ -5597,7 +5675,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
+RUNTIME_FUNCTION(Runtime_DeleteProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
@@ -5613,9 +5691,9 @@
}
-static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate,
- Handle<JSObject> object,
- Handle<Name> key) {
+static Object* HasLocalPropertyImplementation(Isolate* isolate,
+ Handle<JSObject> object,
+ Handle<Name> key) {
if (JSReceiver::HasLocalProperty(object, key)) {
return isolate->heap()->true_value();
}
@@ -5629,16 +5707,16 @@
Handle<JSObject>::cast(proto),
key);
}
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->false_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
+RUNTIME_FUNCTION(Runtime_HasLocalProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0)
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
- Handle<Object> object = args.at<Object>(0);
uint32_t index;
const bool key_is_array_index = key->AsArrayIndex(&index);
@@ -5653,7 +5731,7 @@
ASSERT(!isolate->has_scheduled_exception());
return isolate->heap()->true_value();
} else {
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
}
Map* map = js_obj->map();
if (!key_is_array_index &&
@@ -5676,33 +5754,32 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
+RUNTIME_FUNCTION(Runtime_HasProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
bool result = JSReceiver::HasProperty(receiver, key);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
- if (isolate->has_pending_exception()) return Failure::Exception();
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
+ if (isolate->has_pending_exception()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(result);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
+RUNTIME_FUNCTION(Runtime_HasElement) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
CONVERT_SMI_ARG_CHECKED(index, 1);
bool result = JSReceiver::HasElement(receiver, index);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
- if (isolate->has_pending_exception()) return Failure::Exception();
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->ToBoolean(result);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
+RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -5711,7 +5788,7 @@
PropertyAttributes att = JSReceiver::GetLocalPropertyAttribute(object, key);
if (att == ABSENT || (att & DONT_ENUM) != 0) {
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->false_value();
}
ASSERT(!isolate->has_scheduled_exception());
@@ -5719,7 +5796,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
+RUNTIME_FUNCTION(Runtime_GetPropertyNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
@@ -5728,7 +5805,8 @@
isolate->counters()->for_in()->Increment();
Handle<FixedArray> elements;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, elements, GetKeysInFixedArrayFor(object, INCLUDE_PROTOS));
+ isolate, elements,
+ JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
return *isolate->factory()->NewJSArrayWithElements(elements);
}
@@ -5738,7 +5816,7 @@
// all enumerable properties of the object and its prototypes
// have none, the map of the object. This is used to speed up
// the check for deletions during a for-in.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
+RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -5750,7 +5828,8 @@
Handle<JSReceiver> object(raw_object);
Handle<FixedArray> content;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, content, GetKeysInFixedArrayFor(object, INCLUDE_PROTOS));
+ isolate, content,
+ JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
// Test again, since cache may have been built by preceding call.
if (object->IsSimpleEnum()) return object->map();
@@ -5777,7 +5856,7 @@
// Return the names of the local named properties.
// args[0]: object
// args[1]: PropertyAttributes as int
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
+RUNTIME_FUNCTION(Runtime_GetLocalPropertyNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
if (!args[0]->IsJSObject()) {
@@ -5795,7 +5874,7 @@
!isolate->MayNamedAccess(
obj, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
isolate->ReportFailedAccessCheck(obj, v8::ACCESS_KEYS);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return *isolate->factory()->NewJSArray(0);
}
obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
@@ -5814,7 +5893,7 @@
!isolate->MayNamedAccess(
jsproto, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
isolate->ReportFailedAccessCheck(jsproto, v8::ACCESS_KEYS);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return *isolate->factory()->NewJSArray(0);
}
int n;
@@ -5891,7 +5970,7 @@
// Return the names of the local indexed properties.
// args[0]: object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
+RUNTIME_FUNCTION(Runtime_GetLocalElementNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
if (!args[0]->IsJSObject()) {
@@ -5908,7 +5987,7 @@
// Return information on whether an object has a named or indexed interceptor.
// args[0]: object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
+RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
if (!args[0]->IsJSObject()) {
@@ -5926,14 +6005,16 @@
// Return property names from named interceptor.
// args[0]: object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
+RUNTIME_FUNCTION(Runtime_GetNamedInterceptorPropertyNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
if (obj->HasNamedInterceptor()) {
- v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
- if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+ Handle<JSArray> result;
+ if (JSObject::GetKeysForNamedInterceptor(obj, obj).ToHandle(&result)) {
+ return *result;
+ }
}
return isolate->heap()->undefined_value();
}
@@ -5941,22 +6022,24 @@
// Return element names from indexed interceptor.
// args[0]: object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
+RUNTIME_FUNCTION(Runtime_GetIndexedInterceptorElementNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
if (obj->HasIndexedInterceptor()) {
- v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
- if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+ Handle<JSArray> result;
+ if (JSObject::GetKeysForIndexedInterceptor(obj, obj).ToHandle(&result)) {
+ return *result;
+ }
}
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
+RUNTIME_FUNCTION(Runtime_LocalKeys) {
HandleScope scope(isolate);
- ASSERT_EQ(args.length(), 1);
+ ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
Handle<JSObject> object(raw_object);
@@ -5966,7 +6049,7 @@
!isolate->MayNamedAccess(
object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return *isolate->factory()->NewJSArray(0);
}
@@ -5978,7 +6061,8 @@
Handle<FixedArray> contents;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, contents, GetKeysInFixedArrayFor(object, LOCAL_ONLY));
+ isolate, contents,
+ JSReceiver::GetKeys(object, JSReceiver::LOCAL_ONLY));
// Some fast paths through GetKeysInFixedArrayFor reuse a cached
// property array and since the result is mutable we have to create
@@ -6002,9 +6086,10 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
+RUNTIME_FUNCTION(Runtime_GetArgumentsProperty) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0);
// Compute the frame holding the arguments.
JavaScriptFrameIterator it(isolate);
@@ -6017,25 +6102,25 @@
// Try to convert the key to an index. If successful and within
// index return the the argument from the frame.
uint32_t index;
- if (args[0]->ToArrayIndex(&index) && index < n) {
+ if (raw_key->ToArrayIndex(&index) && index < n) {
return frame->GetParameter(index);
}
HandleScope scope(isolate);
- if (args[0]->IsSymbol()) {
+ if (raw_key->IsSymbol()) {
// Lookup in the initial Object.prototype object.
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
- Object::GetProperty(
- isolate->initial_object_prototype(), args.at<Symbol>(0)));
+ Object::GetProperty(isolate->initial_object_prototype(),
+ Handle<Symbol>::cast(raw_key)));
return *result;
}
// Convert the key to a string.
Handle<Object> converted;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, converted, Execution::ToString(isolate, args.at<Object>(0)));
+ isolate, converted, Execution::ToString(isolate, raw_key));
Handle<String> key = Handle<String>::cast(converted);
// Try to convert the string key into an array index.
@@ -6074,7 +6159,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
+RUNTIME_FUNCTION(Runtime_ToFastProperties) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
@@ -6085,20 +6170,21 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
+RUNTIME_FUNCTION(Runtime_ToBool) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
+ CONVERT_ARG_CHECKED(Object, object, 0);
- return isolate->heap()->ToBoolean(args[0]->BooleanValue());
+ return isolate->heap()->ToBoolean(object->BooleanValue());
}
// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
// Possible optimizations: put the type string into the oddballs.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
+RUNTIME_FUNCTION(Runtime_Typeof) {
SealHandleScope shs(isolate);
-
- Object* obj = args[0];
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_CHECKED(Object, obj, 0);
if (obj->IsNumber()) return isolate->heap()->number_string();
HeapObject* heap_obj = HeapObject::cast(obj);
@@ -6159,7 +6245,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
+RUNTIME_FUNCTION(Runtime_StringToNumber) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
@@ -6222,28 +6308,34 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NewString) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(length, 0);
CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
if (length == 0) return isolate->heap()->empty_string();
+ Handle<String> result;
if (is_one_byte) {
- return isolate->heap()->AllocateRawOneByteString(length);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, isolate->factory()->NewRawOneByteString(length));
} else {
- return isolate->heap()->AllocateRawTwoByteString(length);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, isolate->factory()->NewRawTwoByteString(length));
}
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) {
+RUNTIME_FUNCTION(Runtime_TruncateString) {
HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
CONVERT_SMI_ARG_CHECKED(new_length, 1);
return *SeqString::Truncate(string, new_length);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
+RUNTIME_FUNCTION(Runtime_URIEscape) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
@@ -6259,7 +6351,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
+RUNTIME_FUNCTION(Runtime_URIUnescape) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
@@ -6275,24 +6367,32 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
+RUNTIME_FUNCTION(Runtime_QuoteJSONString) {
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
ASSERT(args.length() == 1);
- return BasicJsonStringifier::StringifyString(isolate, string);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, BasicJsonStringifier::StringifyString(isolate, string));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
+RUNTIME_FUNCTION(Runtime_BasicJSONStringify) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
BasicJsonStringifier stringifier(isolate);
- return stringifier.Stringify(Handle<Object>(args[0], isolate));
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, stringifier.Stringify(object));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
+RUNTIME_FUNCTION(Runtime_StringParseInt) {
HandleScope handle_scope(isolate);
+ ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]);
RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
@@ -6317,8 +6417,9 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
+RUNTIME_FUNCTION(Runtime_StringParseFloat) {
HandleScope shs(isolate);
+ ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
subject = String::Flatten(subject);
@@ -6339,7 +6440,7 @@
template <class Converter>
-MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
+MUST_USE_RESULT static Object* ConvertCaseHelper(
Isolate* isolate,
String* string,
SeqString* result,
@@ -6562,12 +6663,10 @@
template <class Converter>
-MUST_USE_RESULT static MaybeObject* ConvertCase(
- Arguments args,
+MUST_USE_RESULT static Object* ConvertCase(
+ Handle<String> s,
Isolate* isolate,
unibrow::Mapping<Converter, 128>* mapping) {
- HandleScope handle_scope(isolate);
- CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
s = String::Flatten(s);
int length = s->length();
// Assume that the string is not empty; we need this assumption later
@@ -6593,7 +6692,7 @@
length,
&has_changed_character);
// If not ASCII, we discard the result and take the 2 byte path.
- if (is_ascii) return has_changed_character ? *result : *s;
+ if (is_ascii) return has_changed_character ? *result : *s;
}
Handle<SeqString> result; // Same length as input.
@@ -6603,10 +6702,8 @@
result = isolate->factory()->NewRawTwoByteString(length).ToHandleChecked();
}
- MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping);
- Object* answer;
- if (!maybe->ToObject(&answer)) return maybe;
- if (answer->IsString()) return answer;
+ Object* answer = ConvertCaseHelper(isolate, *s, *result, length, mapping);
+ if (answer->IsException() || answer->IsString()) return answer;
ASSERT(answer->IsSmi());
length = Smi::cast(answer)->value();
@@ -6622,19 +6719,25 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
+RUNTIME_FUNCTION(Runtime_StringToLowerCase) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
return ConvertCase(
- args, isolate, isolate->runtime_state()->to_lower_mapping());
+ s, isolate, isolate->runtime_state()->to_lower_mapping());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
+RUNTIME_FUNCTION(Runtime_StringToUpperCase) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
return ConvertCase(
- args, isolate, isolate->runtime_state()->to_upper_mapping());
+ s, isolate, isolate->runtime_state()->to_upper_mapping());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
+RUNTIME_FUNCTION(Runtime_StringTrim) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -6667,7 +6770,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
+RUNTIME_FUNCTION(Runtime_StringSplit) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
@@ -6745,10 +6848,10 @@
if (limit == 0xffffffffu) {
if (result->HasFastObjectElements()) {
- RegExpResultsCache::Enter(isolate->heap(),
- *subject,
- *pattern,
- *elements,
+ RegExpResultsCache::Enter(isolate,
+ subject,
+ pattern,
+ elements,
RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
}
}
@@ -6792,7 +6895,7 @@
// Converts a String to JSArray.
// For example, "foo" => ["f", "o", "o"].
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
+RUNTIME_FUNCTION(Runtime_StringToArray) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
@@ -6805,12 +6908,8 @@
int position = 0;
if (s->IsFlat() && s->IsOneByteRepresentation()) {
// Try using cached chars where possible.
- Object* obj;
- { MaybeObject* maybe_obj =
- isolate->heap()->AllocateUninitializedFixedArray(length);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
- elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
+ elements = isolate->factory()->NewUninitializedFixedArray(length);
+
DisallowHeapAllocation no_gc;
String::FlatContent content = s->GetFlatContent();
if (content.IsAscii()) {
@@ -6845,7 +6944,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
+RUNTIME_FUNCTION(Runtime_NewStringWrapper) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, value, 0);
@@ -6860,91 +6959,70 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NumberToString) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_NumberToString) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
- Object* number = args[0];
- RUNTIME_ASSERT(number->IsNumber());
-
- return isolate->heap()->NumberToString(number);
+ return *isolate->factory()->NumberToString(number);
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NumberToStringSkipCache) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_NumberToStringSkipCache) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
- Object* number = args[0];
- RUNTIME_ASSERT(number->IsNumber());
-
- return isolate->heap()->NumberToString(number, false);
+ return *isolate->factory()->NumberToString(number, false);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToInteger) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(number, 0);
-
- // We do not include 0 so that we don't have to treat +0 / -0 cases.
- if (number > 0 && number <= Smi::kMaxValue) {
- return Smi::FromInt(static_cast<int>(number));
- }
- return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
+ return *isolate->factory()->NewNumber(DoubleToInteger(number));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(number, 0);
-
- // We do not include 0 so that we don't have to treat +0 / -0 cases.
- if (number > 0 && number <= Smi::kMaxValue) {
- return Smi::FromInt(static_cast<int>(number));
- }
-
double double_value = DoubleToInteger(number);
// Map both -0 and +0 to +0.
if (double_value == 0) double_value = 0;
- return isolate->heap()->NumberFromDouble(double_value);
+ return *isolate->factory()->NewNumber(double_value);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToJSUint32) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
- return isolate->heap()->NumberFromUint32(number);
+ return *isolate->factory()->NewNumberFromUint(number);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToJSInt32) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(number, 0);
-
- // We do not include 0 so that we don't have to treat +0 / -0 cases.
- if (number > 0 && number <= Smi::kMaxValue) {
- return Smi::FromInt(static_cast<int>(number));
- }
- return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
+ return *isolate->factory()->NewNumberFromInt(DoubleToInt32(number));
}
// Converts a Number to a Smi, if possible. Returns NaN if the number is not
// a small integer.
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NumberToSmi) {
+RUNTIME_FUNCTION(RuntimeHidden_NumberToSmi) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
-
- Object* obj = args[0];
+ CONVERT_ARG_CHECKED(Object, obj, 0);
if (obj->IsSmi()) {
return obj;
}
@@ -6959,94 +7037,83 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_AllocateHeapNumber) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_AllocateHeapNumber) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 0);
- return isolate->heap()->AllocateHeapNumber(0);
+ return *isolate->factory()->NewHeapNumber(0);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberAdd) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
- return isolate->heap()->NumberFromDouble(x + y);
+ return *isolate->factory()->NewNumber(x + y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberSub) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
- return isolate->heap()->NumberFromDouble(x - y);
+ return *isolate->factory()->NewNumber(x - y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberMul) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
- return isolate->heap()->NumberFromDouble(x * y);
+ return *isolate->factory()->NewNumber(x * y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberUnaryMinus) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->heap()->NumberFromDouble(-x);
+ return *isolate->factory()->NewNumber(-x);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 0);
-
- return isolate->heap()->NumberFromDouble(9876543210.0);
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberDiv) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
- return isolate->heap()->NumberFromDouble(x / y);
+ return *isolate->factory()->NewNumber(x / y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberMod) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
-
- x = modulo(x, y);
- // NumberFromDouble may return a Smi instead of a Number object
- return isolate->heap()->NumberFromDouble(x);
+ return *isolate->factory()->NewNumber(modulo(x, y));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberImul) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberImul) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(x * y);
+ return *isolate->factory()->NewNumberFromInt(x * y);
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringAdd) {
+RUNTIME_FUNCTION(RuntimeHidden_StringAdd) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
@@ -7064,6 +7131,7 @@
sinkchar* sink,
FixedArray* fixed_array,
int array_length) {
+ DisallowHeapAllocation no_gc;
int position = 0;
for (int i = 0; i < array_length; i++) {
Object* element = fixed_array->get(i);
@@ -7098,36 +7166,13 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 3);
- CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
- if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
- int array_length = args.smi_at(1);
- CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
-
- // This assumption is used by the slice encoding in one or two smis.
- ASSERT(Smi::kMaxValue >= String::kMaxLength);
-
- JSObject::EnsureCanContainHeapObjectElements(array);
-
- int special_length = special->length();
- if (!array->HasFastObjectElements()) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
- FixedArray* fixed_array = FixedArray::cast(array->elements());
- if (fixed_array->length() < array_length) {
- array_length = fixed_array->length();
- }
-
- if (array_length == 0) {
- return isolate->heap()->empty_string();
- } else if (array_length == 1) {
- Object* first = fixed_array->get(0);
- if (first->IsString()) return first;
- }
-
- bool one_byte = special->HasOnlyOneByteChars();
+// Returns the result length of the concatenation.
+// On illegal argument, -1 is returned.
+static inline int StringBuilderConcatLength(int special_length,
+ FixedArray* fixed_array,
+ int array_length,
+ bool* one_byte) {
+ DisallowHeapAllocation no_gc;
int position = 0;
for (int i = 0; i < array_length; i++) {
int increment = 0;
@@ -7146,76 +7191,107 @@
len = -smi_value;
// Get the position and check that it is a positive smi.
i++;
- if (i >= array_length) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
+ if (i >= array_length) return -1;
Object* next_smi = fixed_array->get(i);
- if (!next_smi->IsSmi()) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
+ if (!next_smi->IsSmi()) return -1;
pos = Smi::cast(next_smi)->value();
- if (pos < 0) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
+ if (pos < 0) return -1;
}
ASSERT(pos >= 0);
ASSERT(len >= 0);
- if (pos > special_length || len > special_length - pos) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
+ if (pos > special_length || len > special_length - pos) return -1;
increment = len;
} else if (elt->IsString()) {
String* element = String::cast(elt);
int element_length = element->length();
increment = element_length;
- if (one_byte && !element->HasOnlyOneByteChars()) {
- one_byte = false;
+ if (*one_byte && !element->HasOnlyOneByteChars()) {
+ *one_byte = false;
}
} else {
ASSERT(!elt->IsTheHole());
- return isolate->Throw(isolate->heap()->illegal_argument_string());
+ return -1;
}
if (increment > String::kMaxLength - position) {
- return isolate->ThrowInvalidStringLength();
+ return kMaxInt; // Provoke throw on allocation.
}
position += increment;
}
-
- int length = position;
- Object* object;
-
- if (one_byte) {
- { MaybeObject* maybe_object =
- isolate->heap()->AllocateRawOneByteString(length);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- SeqOneByteString* answer = SeqOneByteString::cast(object);
- StringBuilderConcatHelper(*special,
- answer->GetChars(),
- fixed_array,
- array_length);
- return answer;
- } else {
- { MaybeObject* maybe_object =
- isolate->heap()->AllocateRawTwoByteString(length);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- SeqTwoByteString* answer = SeqTwoByteString::cast(object);
- StringBuilderConcatHelper(*special,
- answer->GetChars(),
- fixed_array,
- array_length);
- return answer;
- }
+ return position;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
+RUNTIME_FUNCTION(Runtime_StringBuilderConcat) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
- int array_length = args.smi_at(1);
+ CONVERT_SMI_ARG_CHECKED(array_length, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
+
+ // This assumption is used by the slice encoding in one or two smis.
+ ASSERT(Smi::kMaxValue >= String::kMaxLength);
+
+ JSObject::EnsureCanContainHeapObjectElements(array);
+
+ int special_length = special->length();
+ if (!array->HasFastObjectElements()) {
+ return isolate->Throw(isolate->heap()->illegal_argument_string());
+ }
+
+ int length;
+ bool one_byte = special->HasOnlyOneByteChars();
+
+ { DisallowHeapAllocation no_gc;
+ FixedArray* fixed_array = FixedArray::cast(array->elements());
+ if (fixed_array->length() < array_length) {
+ array_length = fixed_array->length();
+ }
+
+ if (array_length == 0) {
+ return isolate->heap()->empty_string();
+ } else if (array_length == 1) {
+ Object* first = fixed_array->get(0);
+ if (first->IsString()) return first;
+ }
+ length = StringBuilderConcatLength(
+ special_length, fixed_array, array_length, &one_byte);
+ }
+
+ if (length == -1) {
+ return isolate->Throw(isolate->heap()->illegal_argument_string());
+ }
+
+ if (one_byte) {
+ Handle<SeqOneByteString> answer;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, answer,
+ isolate->factory()->NewRawOneByteString(length));
+ StringBuilderConcatHelper(*special,
+ answer->GetChars(),
+ FixedArray::cast(array->elements()),
+ array_length);
+ return *answer;
+ } else {
+ Handle<SeqTwoByteString> answer;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, answer,
+ isolate->factory()->NewRawTwoByteString(length));
+ StringBuilderConcatHelper(*special,
+ answer->GetChars(),
+ FixedArray::cast(array->elements()),
+ array_length);
+ return *answer;
+ }
+}
+
+
+RUNTIME_FUNCTION(Runtime_StringBuilderJoin) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 3);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
+ if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
+ CONVERT_SMI_ARG_CHECKED(array_length, 1);
CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
RUNTIME_ASSERT(array->HasFastObjectElements());
@@ -7294,6 +7370,7 @@
uint32_t array_length,
String* separator,
Vector<Char> buffer) {
+ DisallowHeapAllocation no_gc;
int previous_separator_position = 0;
int separator_length = separator->length();
int cursor = 0;
@@ -7329,13 +7406,13 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
+RUNTIME_FUNCTION(Runtime_SparseJoinWithSeparator) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
- CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, elements_array, 0);
RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
- CONVERT_ARG_CHECKED(String, separator, 2);
+ CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
// elements_array is fast-mode JSarray of alternating positions
// (increasing order) and strings.
// array_length is length of original array (used to add separators);
@@ -7345,25 +7422,28 @@
int string_length = 0;
bool is_ascii = separator->IsOneByteRepresentation();
bool overflow = false;
- CONVERT_NUMBER_CHECKED(int, elements_length,
- Int32, elements_array->length());
+ CONVERT_NUMBER_CHECKED(int, elements_length, Int32, elements_array->length());
RUNTIME_ASSERT((elements_length & 1) == 0); // Even length.
- FixedArray* elements = FixedArray::cast(elements_array->elements());
- for (int i = 0; i < elements_length; i += 2) {
- RUNTIME_ASSERT(elements->get(i)->IsNumber());
- RUNTIME_ASSERT(elements->get(i + 1)->IsString());
- String* string = String::cast(elements->get(i + 1));
- int length = string->length();
- if (is_ascii && !string->IsOneByteRepresentation()) {
- is_ascii = false;
+
+ { DisallowHeapAllocation no_gc;
+ FixedArray* elements = FixedArray::cast(elements_array->elements());
+ for (int i = 0; i < elements_length; i += 2) {
+ RUNTIME_ASSERT(elements->get(i)->IsNumber());
+ RUNTIME_ASSERT(elements->get(i + 1)->IsString());
+ String* string = String::cast(elements->get(i + 1));
+ int length = string->length();
+ if (is_ascii && !string->IsOneByteRepresentation()) {
+ is_ascii = false;
+ }
+ if (length > String::kMaxLength ||
+ String::kMaxLength - length < string_length) {
+ overflow = true;
+ break;
+ }
+ string_length += length;
}
- if (length > String::kMaxLength ||
- String::kMaxLength - length < string_length) {
- overflow = true;
- break;
- }
- string_length += length;
}
+
int separator_length = separator->length();
if (!overflow && separator_length > 0) {
if (array_length <= 0x7fffffffu) {
@@ -7390,97 +7470,91 @@
}
if (is_ascii) {
- MaybeObject* result_allocation =
- isolate->heap()->AllocateRawOneByteString(string_length);
- if (result_allocation->IsFailure()) return result_allocation;
- SeqOneByteString* result_string =
- SeqOneByteString::cast(result_allocation->ToObjectUnchecked());
- JoinSparseArrayWithSeparator<uint8_t>(elements,
- elements_length,
- array_length,
- separator,
- Vector<uint8_t>(
- result_string->GetChars(),
- string_length));
- return result_string;
+ Handle<SeqOneByteString> result = isolate->factory()->NewRawOneByteString(
+ string_length).ToHandleChecked();
+ JoinSparseArrayWithSeparator<uint8_t>(
+ FixedArray::cast(elements_array->elements()),
+ elements_length,
+ array_length,
+ *separator,
+ Vector<uint8_t>(result->GetChars(), string_length));
+ return *result;
} else {
- MaybeObject* result_allocation =
- isolate->heap()->AllocateRawTwoByteString(string_length);
- if (result_allocation->IsFailure()) return result_allocation;
- SeqTwoByteString* result_string =
- SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
- JoinSparseArrayWithSeparator<uc16>(elements,
- elements_length,
- array_length,
- separator,
- Vector<uc16>(result_string->GetChars(),
- string_length));
- return result_string;
+ Handle<SeqTwoByteString> result = isolate->factory()->NewRawTwoByteString(
+ string_length).ToHandleChecked();
+ JoinSparseArrayWithSeparator<uc16>(
+ FixedArray::cast(elements_array->elements()),
+ elements_length,
+ array_length,
+ *separator,
+ Vector<uc16>(result->GetChars(), string_length));
+ return *result;
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberOr) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(x | y);
+ return *isolate->factory()->NewNumberFromInt(x | y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberAnd) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(x & y);
+ return *isolate->factory()->NewNumberFromInt(x & y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberXor) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(x ^ y);
+ return *isolate->factory()->NewNumberFromInt(x ^ y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberShl) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
+ return *isolate->factory()->NewNumberFromInt(x << (y & 0x1f));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberShr) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
+ return *isolate->factory()->NewNumberFromUint(x >> (y & 0x1f));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberSar) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
+ return *isolate->factory()->NewNumberFromInt(
+ ArithmeticShiftRight(x, y & 0x1f));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
+RUNTIME_FUNCTION(Runtime_NumberEquals) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -7499,7 +7573,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
+RUNTIME_FUNCTION(Runtime_StringEquals) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
@@ -7517,7 +7591,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
+RUNTIME_FUNCTION(Runtime_NumberCompare) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 3);
@@ -7532,7 +7606,7 @@
// Compare two Smis as if they were converted to strings and then
// compared lexicographically.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
+RUNTIME_FUNCTION(Runtime_SmiLexicographicCompare) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(x_value, 0);
@@ -7607,7 +7681,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) {
+RUNTIME_FUNCTION(RuntimeHidden_StringCompare) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
@@ -7675,12 +7749,12 @@
#define RUNTIME_UNARY_MATH(Name, name) \
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math##Name) { \
- SealHandleScope shs(isolate); \
+RUNTIME_FUNCTION(Runtime_Math##Name) { \
+ HandleScope scope(isolate); \
ASSERT(args.length() == 1); \
isolate->counters()->math_##name()->Increment(); \
CONVERT_DOUBLE_ARG_CHECKED(x, 0); \
- return isolate->heap()->AllocateHeapNumber(std::name(x)); \
+ return *isolate->factory()->NewHeapNumber(std::name(x)); \
}
RUNTIME_UNARY_MATH(Acos, acos)
@@ -7690,40 +7764,40 @@
#undef RUNTIME_UNARY_MATH
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DoubleHi) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DoubleHi) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
uint64_t integer = double_to_uint64(x);
integer = (integer >> 32) & 0xFFFFFFFFu;
- return isolate->heap()->NumberFromDouble(static_cast<int32_t>(integer));
+ return *isolate->factory()->NewNumber(static_cast<int32_t>(integer));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DoubleLo) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DoubleLo) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->heap()->NumberFromDouble(
+ return *isolate->factory()->NewNumber(
static_cast<int32_t>(double_to_uint64(x) & 0xFFFFFFFFu));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ConstructDouble) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_ConstructDouble) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
- return isolate->heap()->AllocateHeapNumber(uint64_to_double(result));
+ return *isolate->factory()->NewNumber(uint64_to_double(result));
}
static const double kPiDividedBy4 = 0.78539816339744830962;
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MathAtan2) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MathAtan2) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
isolate->counters()->math_atan2()->Increment();
@@ -7741,35 +7815,35 @@
} else {
result = std::atan2(x, y);
}
- return isolate->heap()->AllocateHeapNumber(result);
+ return *isolate->factory()->NewNumber(result);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MathExp) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MathExp) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
isolate->counters()->math_exp()->Increment();
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
lazily_initialize_fast_exp();
- return isolate->heap()->NumberFromDouble(fast_exp(x));
+ return *isolate->factory()->NewNumber(fast_exp(x));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MathFloor) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MathFloor) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
isolate->counters()->math_floor()->Increment();
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->heap()->NumberFromDouble(std::floor(x));
+ return *isolate->factory()->NewNumber(std::floor(x));
}
// Slow version of Math.pow. We check for fast paths for special cases.
// Used if SSE2/VFP3 is not available.
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_MathPowSlow) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_MathPowSlow) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
isolate->counters()->math_pow()->Increment();
@@ -7779,20 +7853,20 @@
// custom powi() function than the generic pow().
if (args[1]->IsSmi()) {
int y = args.smi_at(1);
- return isolate->heap()->NumberFromDouble(power_double_int(x, y));
+ return *isolate->factory()->NewNumber(power_double_int(x, y));
}
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
double result = power_helper(x, y);
if (std::isnan(result)) return isolate->heap()->nan_value();
- return isolate->heap()->AllocateHeapNumber(result);
+ return *isolate->factory()->NewNumber(result);
}
// Fast version of Math.pow if we know that y is not an integer and y is not
// -0.5 or 0.5. Used as slow case from full codegen.
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_MathPow) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_MathPow) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
isolate->counters()->math_pow()->Increment();
@@ -7803,13 +7877,13 @@
} else {
double result = power_double_double(x, y);
if (std::isnan(result)) return isolate->heap()->nan_value();
- return isolate->heap()->AllocateHeapNumber(result);
+ return *isolate->factory()->NewNumber(result);
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_RoundNumber) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
isolate->counters()->math_round()->Increment();
@@ -7847,31 +7921,31 @@
if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
// Do not call NumberFromDouble() to avoid extra checks.
- return isolate->heap()->AllocateHeapNumber(std::floor(value + 0.5));
+ return *isolate->factory()->NewNumber(std::floor(value + 0.5));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MathSqrt) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MathSqrt) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
isolate->counters()->math_sqrt()->Increment();
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
+ return *isolate->factory()->NewNumber(fast_sqrt(x));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MathFround) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MathFround) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
float xf = static_cast<float>(x);
- return isolate->heap()->AllocateHeapNumber(xf);
+ return *isolate->factory()->NewNumber(xf);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
+RUNTIME_FUNCTION(Runtime_DateMakeDay) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -7882,7 +7956,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
+RUNTIME_FUNCTION(Runtime_DateSetValue) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -7892,40 +7966,38 @@
DateCache* date_cache = isolate->date_cache();
- Object* value = NULL;
+ Handle<Object> value;;
bool is_value_nan = false;
if (std::isnan(time)) {
- value = isolate->heap()->nan_value();
+ value = isolate->factory()->nan_value();
is_value_nan = true;
} else if (!is_utc &&
(time < -DateCache::kMaxTimeBeforeUTCInMs ||
time > DateCache::kMaxTimeBeforeUTCInMs)) {
- value = isolate->heap()->nan_value();
+ value = isolate->factory()->nan_value();
is_value_nan = true;
} else {
time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
if (time < -DateCache::kMaxTimeInMs ||
time > DateCache::kMaxTimeInMs) {
- value = isolate->heap()->nan_value();
+ value = isolate->factory()->nan_value();
is_value_nan = true;
} else {
- MaybeObject* maybe_result =
- isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
- if (!maybe_result->ToObject(&value)) return maybe_result;
+ value = isolate->factory()->NewNumber(DoubleToInteger(time));
}
}
- date->SetValue(value, is_value_nan);
- return value;
+ date->SetValue(*value, is_value_nan);
+ return *value;
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewArgumentsFast) {
+RUNTIME_FUNCTION(RuntimeHidden_NewArgumentsFast) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
- Handle<JSFunction> callee = args.at<JSFunction>(0);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
Object** parameters = reinterpret_cast<Object**>(args[1]);
- const int argument_count = Smi::cast(args[2])->value();
+ CONVERT_SMI_ARG_CHECKED(argument_count, 2);
Handle<JSObject> result =
isolate->factory()->NewArgumentsObject(callee, argument_count);
@@ -8013,54 +8085,42 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewStrictArgumentsFast) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_NewStrictArgumentsFast) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
-
- JSFunction* callee = JSFunction::cast(args[0]);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
Object** parameters = reinterpret_cast<Object**>(args[1]);
- const int length = args.smi_at(2);
+ CONVERT_SMI_ARG_CHECKED(length, 2);
- Object* result;
- { MaybeObject* maybe_result =
- isolate->heap()->AllocateArgumentsObject(callee, length);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- // Allocate the elements if needed.
+ Handle<JSObject> result =
+ isolate->factory()->NewArgumentsObject(callee, length);
+
if (length > 0) {
- // Allocate the fixed array.
- FixedArray* array;
- { MaybeObject* maybe_obj =
- isolate->heap()->AllocateUninitializedFixedArray(length);
- if (!maybe_obj->To(&array)) return maybe_obj;
- }
-
+ Handle<FixedArray> array =
+ isolate->factory()->NewUninitializedFixedArray(length);
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) {
array->set(i, *--parameters, mode);
}
- JSObject::cast(result)->set_elements(array);
+ result->set_elements(*array);
}
- return result;
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewClosureFromStubFailure) {
+RUNTIME_FUNCTION(RuntimeHidden_NewClosureFromStubFailure) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
Handle<Context> context(isolate->context());
PretenureFlag pretenure_flag = NOT_TENURED;
- Handle<JSFunction> result =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
- context,
- pretenure_flag);
- return *result;
+ return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
+ shared, context, pretenure_flag);
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewClosure) {
+RUNTIME_FUNCTION(RuntimeHidden_NewClosure) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
@@ -8070,11 +8130,8 @@
// The caller ensures that we pretenure closures that are assigned
// directly to properties.
PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
- Handle<JSFunction> result =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
- context,
- pretenure_flag);
- return *result;
+ return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
+ shared, context, pretenure_flag);
}
@@ -8128,7 +8185,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
+RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
@@ -8189,7 +8246,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
+RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) {
HandleScope handles(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
@@ -8205,7 +8262,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
+RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
// First argument is a function to use as a constructor.
@@ -8247,7 +8304,7 @@
}
-static MaybeObject* Runtime_NewObjectHelper(Isolate* isolate,
+static Object* Runtime_NewObjectHelper(Isolate* isolate,
Handle<Object> constructor,
Handle<AllocationSite> site) {
// If the constructor isn't a proper function we throw a type error.
@@ -8313,7 +8370,6 @@
} else {
result = isolate->factory()->NewJSObjectWithMemento(function, site);
}
- RETURN_IF_EMPTY_HANDLE(isolate, result);
isolate->counters()->constructed_objects()->Increment();
isolate->counters()->constructed_objects_runtime()->Increment();
@@ -8322,35 +8378,31 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewObject) {
+RUNTIME_FUNCTION(RuntimeHidden_NewObject) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
-
- Handle<Object> constructor = args.at<Object>(0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
return Runtime_NewObjectHelper(isolate,
constructor,
Handle<AllocationSite>::null());
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewObjectWithAllocationSite) {
+RUNTIME_FUNCTION(RuntimeHidden_NewObjectWithAllocationSite) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
-
- Handle<Object> constructor = args.at<Object>(1);
- Handle<Object> feedback = args.at<Object>(0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, feedback, 0);
Handle<AllocationSite> site;
if (feedback->IsAllocationSite()) {
// The feedback can be an AllocationSite or undefined.
site = Handle<AllocationSite>::cast(feedback);
}
- return Runtime_NewObjectHelper(isolate,
- constructor,
- site);
+ return Runtime_NewObjectHelper(isolate, constructor, site);
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_FinalizeInstanceSize) {
+RUNTIME_FUNCTION(RuntimeHidden_FinalizeInstanceSize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -8361,11 +8413,10 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CompileUnoptimized) {
+RUNTIME_FUNCTION(RuntimeHidden_CompileUnoptimized) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
-
- Handle<JSFunction> function = args.at<JSFunction>(0);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
#ifdef DEBUG
if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
PrintF("[unoptimized: ");
@@ -8377,8 +8428,9 @@
// Compile the target function.
ASSERT(function->shared()->allows_lazy_compilation());
- Handle<Code> code = Compiler::GetUnoptimizedCode(function);
- RETURN_IF_EMPTY_HANDLE(isolate, code);
+ Handle<Code> code;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, code,
+ Compiler::GetUnoptimizedCode(function));
function->ReplaceCode(*code);
// All done. Return the compiled code.
@@ -8390,10 +8442,10 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CompileOptimized) {
+RUNTIME_FUNCTION(RuntimeHidden_CompileOptimized) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
- Handle<JSFunction> function = args.at<JSFunction>(0);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
CONVERT_BOOLEAN_ARG_CHECKED(concurrent, 1);
Handle<Code> unoptimized(function->shared()->code());
@@ -8419,8 +8471,13 @@
} else {
Compiler::ConcurrencyMode mode = concurrent ? Compiler::CONCURRENT
: Compiler::NOT_CONCURRENT;
- Handle<Code> code = Compiler::GetOptimizedCode(function, unoptimized, mode);
- function->ReplaceCode(code.is_null() ? *unoptimized : *code);
+ Handle<Code> code;
+ if (Compiler::GetOptimizedCode(
+ function, unoptimized, mode).ToHandle(&code)) {
+ function->ReplaceCode(*code);
+ } else {
+ function->ReplaceCode(*unoptimized);
+ }
}
ASSERT(function->code()->kind() == Code::FUNCTION ||
@@ -8453,7 +8510,7 @@
};
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NotifyStubFailure) {
+RUNTIME_FUNCTION(RuntimeHidden_NotifyStubFailure) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
@@ -8463,12 +8520,12 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NotifyDeoptimized) {
+RUNTIME_FUNCTION(RuntimeHidden_NotifyDeoptimized) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- RUNTIME_ASSERT(args[0]->IsSmi());
+ CONVERT_SMI_ARG_CHECKED(type_arg, 0);
Deoptimizer::BailoutType type =
- static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
+ static_cast<Deoptimizer::BailoutType>(type_arg);
Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
ASSERT(AllowHeapAllocation::IsAllowed());
@@ -8522,7 +8579,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
+RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -8534,7 +8591,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
+RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -8547,8 +8604,9 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
+RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 0);
#if defined(USE_SIMULATOR)
return isolate->heap()->true_value();
#else
@@ -8557,14 +8615,14 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsConcurrentRecompilationSupported) {
- HandleScope scope(isolate);
- return isolate->concurrent_recompilation_enabled()
- ? isolate->heap()->true_value() : isolate->heap()->false_value();
+RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
+ SealHandleScope shs(isolate);
+ return isolate->heap()->ToBoolean(
+ isolate->concurrent_recompilation_enabled());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
+RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -8599,7 +8657,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NeverOptimizeFunction) {
+RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, function, 0);
@@ -8608,7 +8666,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
+RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
if (!isolate->use_crankshaft()) {
@@ -8643,7 +8701,8 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_UnblockConcurrentRecompilation) {
+RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
+ ASSERT(args.length() == 0);
RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
isolate->optimizing_compiler_thread()->Unblock();
@@ -8651,7 +8710,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
+RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -8678,7 +8737,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
+RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -8739,15 +8798,16 @@
PrintF(" at AST id %d]\n", ast_id.ToInt());
}
result = Compiler::GetConcurrentlyOptimizedCode(job);
- } else if (result.is_null() &&
- IsSuitableForOnStackReplacement(isolate, function, caller_code)) {
+ } else if (IsSuitableForOnStackReplacement(isolate, function, caller_code)) {
if (FLAG_trace_osr) {
PrintF("[OSR - Compiling: ");
function->PrintName();
PrintF(" at AST id %d]\n", ast_id.ToInt());
}
- result = Compiler::GetOptimizedCode(function, caller_code, mode, ast_id);
- if (result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
+ MaybeHandle<Code> maybe_result = Compiler::GetOptimizedCode(
+ function, caller_code, mode, ast_id);
+ if (maybe_result.ToHandle(&result) &&
+ result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
// Optimization is queued. Return to check later.
return NULL;
}
@@ -8791,7 +8851,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAllocationTimeout) {
+RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2 || args.length() == 3);
#ifdef DEBUG
@@ -8813,21 +8873,23 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
+RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 0);
RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
+RUNTIME_FUNCTION(Runtime_GetRootNaN) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 0);
RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
return isolate->heap()->nan_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
+RUNTIME_FUNCTION(Runtime_Call) {
HandleScope scope(isolate);
ASSERT(args.length() >= 2);
int argc = args.length() - 2;
@@ -8846,10 +8908,7 @@
}
for (int i = 0; i < argc; ++i) {
- MaybeObject* maybe = args[1 + i];
- Object* object;
- if (!maybe->To<Object>(&object)) return maybe;
- argv[i] = Handle<Object>(object, isolate);
+ argv[i] = Handle<Object>(args[1 + i], isolate);
}
Handle<JSReceiver> hfun(fun);
@@ -8862,11 +8921,11 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
+RUNTIME_FUNCTION(Runtime_Apply) {
HandleScope scope(isolate);
ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
- Handle<Object> receiver = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
CONVERT_SMI_ARG_CHECKED(offset, 3);
CONVERT_SMI_ARG_CHECKED(argc, 4);
@@ -8898,23 +8957,25 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
+RUNTIME_FUNCTION(Runtime_GetFunctionDelegate) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- RUNTIME_ASSERT(!args[0]->IsJSFunction());
- return *Execution::GetFunctionDelegate(isolate, args.at<Object>(0));
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ RUNTIME_ASSERT(!object->IsJSFunction());
+ return *Execution::GetFunctionDelegate(isolate, object);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
+RUNTIME_FUNCTION(Runtime_GetConstructorDelegate) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- RUNTIME_ASSERT(!args[0]->IsJSFunction());
- return *Execution::GetConstructorDelegate(isolate, args.at<Object>(0));
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ RUNTIME_ASSERT(!object->IsJSFunction());
+ return *Execution::GetConstructorDelegate(isolate, object);
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewGlobalContext) {
+RUNTIME_FUNCTION(RuntimeHidden_NewGlobalContext) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -8930,19 +8991,17 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewFunctionContext) {
+RUNTIME_FUNCTION(RuntimeHidden_NewFunctionContext) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
int length = function->shared()->scope_info()->ContextLength();
- Handle<Context> context =
- isolate->factory()->NewFunctionContext(length, function);
- return *context;
+ return *isolate->factory()->NewFunctionContext(length, function);
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushWithContext) {
+RUNTIME_FUNCTION(RuntimeHidden_PushWithContext) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
Handle<JSReceiver> extension_object;
@@ -8979,7 +9038,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushCatchContext) {
+RUNTIME_FUNCTION(RuntimeHidden_PushCatchContext) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
@@ -9001,7 +9060,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushBlockContext) {
+RUNTIME_FUNCTION(RuntimeHidden_PushBlockContext) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
@@ -9022,15 +9081,15 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) {
+RUNTIME_FUNCTION(Runtime_IsJSModule) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* obj = args[0];
+ CONVERT_ARG_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSModule());
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushModuleContext) {
+RUNTIME_FUNCTION(RuntimeHidden_PushModuleContext) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(index, 0);
@@ -9065,7 +9124,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeclareModules) {
+RUNTIME_FUNCTION(RuntimeHidden_DeclareModules) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
@@ -9090,8 +9149,9 @@
IsImmutableVariableMode(mode) ? FROZEN : SEALED;
Handle<AccessorInfo> info =
Accessors::MakeModuleExport(name, index, attr);
- Handle<Object> result = JSObject::SetAccessor(module, info);
- ASSERT(!(result.is_null() || result->IsUndefined()));
+ Handle<Object> result =
+ JSObject::SetAccessor(module, info).ToHandleChecked();
+ ASSERT(!result->IsUndefined());
USE(result);
break;
}
@@ -9110,7 +9170,7 @@
}
}
- JSObject::PreventExtensions(module);
+ JSObject::PreventExtensions(module).Assert();
}
ASSERT(!isolate->has_pending_exception());
@@ -9118,7 +9178,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeleteContextSlot) {
+RUNTIME_FUNCTION(RuntimeHidden_DeleteContextSlot) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -9167,12 +9227,12 @@
// allocated by the caller, and passed as a pointer in a hidden first parameter.
#ifdef V8_HOST_ARCH_64_BIT
struct ObjectPair {
- MaybeObject* x;
- MaybeObject* y;
+ Object* x;
+ Object* y;
};
-static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
+static inline ObjectPair MakePair(Object* x, Object* y) {
ObjectPair result = {x, y};
// Pointers x and y returned in rax and rdx, in AMD-x64-abi.
// In Win64 they are assigned to a hidden first argument.
@@ -9180,22 +9240,20 @@
}
#else
typedef uint64_t ObjectPair;
-static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
+static inline ObjectPair MakePair(Object* x, Object* y) {
+#if defined(V8_TARGET_LITTLE_ENDIAN)
return reinterpret_cast<uint32_t>(x) |
(reinterpret_cast<ObjectPair>(y) << 32);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+ return reinterpret_cast<uint32_t>(y) |
+ (reinterpret_cast<ObjectPair>(x) << 32);
+#else
+#error Unknown endianness
+#endif
}
#endif
-static inline MaybeObject* Unhole(Heap* heap,
- MaybeObject* x,
- PropertyAttributes attributes) {
- ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
- USE(attributes);
- return x->IsTheHole() ? heap->undefined_value() : x;
-}
-
-
static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
JSObject* holder) {
ASSERT(!holder->IsGlobalObject());
@@ -9238,7 +9296,7 @@
&attributes,
&binding_flags);
if (isolate->has_pending_exception()) {
- return MakePair(Failure::Exception(), NULL);
+ return MakePair(isolate->heap()->exception(), NULL);
}
// If the index is non-negative, the slot has been found in a context.
@@ -9265,7 +9323,11 @@
ASSERT(!value->IsTheHole());
return MakePair(value, *receiver);
case IMMUTABLE_CHECK_INITIALIZED:
- return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
+ if (value->IsTheHole()) {
+ ASSERT((attributes & READ_ONLY) != 0);
+ value = isolate->heap()->undefined_value();
+ }
+ return MakePair(value, *receiver);
case MISSING_BINDING:
UNREACHABLE();
return MakePair(NULL, NULL);
@@ -9292,7 +9354,7 @@
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value,
Object::GetProperty(object, name),
- MakePair(Failure::Exception(), NULL));
+ MakePair(isolate->heap()->exception(), NULL));
return MakePair(*value, *receiver_handle);
}
@@ -9310,21 +9372,21 @@
}
-RUNTIME_FUNCTION(ObjectPair, RuntimeHidden_LoadContextSlot) {
+RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_LoadContextSlot) {
return LoadContextSlotHelper(args, isolate, true);
}
-RUNTIME_FUNCTION(ObjectPair, RuntimeHidden_LoadContextSlotNoReferenceError) {
+RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_LoadContextSlotNoReferenceError) {
return LoadContextSlotHelper(args, isolate, false);
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StoreContextSlot) {
+RUNTIME_FUNCTION(RuntimeHidden_StoreContextSlot) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
- Handle<Object> value(args[0], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3);
@@ -9338,7 +9400,7 @@
&index,
&attributes,
&binding_flags);
- if (isolate->has_pending_exception()) return Failure::Exception();
+ if (isolate->has_pending_exception()) return isolate->heap()->exception();
if (index >= 0) {
// The property was found in a context slot.
@@ -9405,7 +9467,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_Throw) {
+RUNTIME_FUNCTION(RuntimeHidden_Throw) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -9413,7 +9475,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ReThrow) {
+RUNTIME_FUNCTION(RuntimeHidden_ReThrow) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -9421,18 +9483,17 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PromoteScheduledException) {
+RUNTIME_FUNCTION(RuntimeHidden_PromoteScheduledException) {
SealHandleScope shs(isolate);
- ASSERT_EQ(0, args.length());
+ ASSERT(args.length() == 0);
return isolate->PromoteScheduledException();
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowReferenceError) {
+RUNTIME_FUNCTION(RuntimeHidden_ThrowReferenceError) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
-
- Handle<Object> name(args[0], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
Handle<Object> reference_error =
isolate->factory()->NewReferenceError("not_defined",
HandleVector(&name, 1));
@@ -9440,7 +9501,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowNotDateError) {
+RUNTIME_FUNCTION(RuntimeHidden_ThrowNotDateError) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
return isolate->Throw(*isolate->factory()->NewTypeError(
@@ -9448,20 +9509,19 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowMessage) {
+RUNTIME_FUNCTION(RuntimeHidden_ThrowMessage) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_SMI_ARG_CHECKED(message_id, 0);
const char* message = GetBailoutReason(
static_cast<BailoutReason>(message_id));
Handle<String> message_handle =
- isolate->factory()->NewStringFromAscii(CStrVector(message));
- RETURN_IF_EMPTY_HANDLE(isolate, message_handle);
+ isolate->factory()->NewStringFromAsciiChecked(message);
return isolate->Throw(*message_handle);
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StackGuard) {
+RUNTIME_FUNCTION(RuntimeHidden_StackGuard) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
@@ -9474,7 +9534,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_TryInstallOptimizedCode) {
+RUNTIME_FUNCTION(RuntimeHidden_TryInstallOptimizedCode) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -9491,7 +9551,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_Interrupt) {
+RUNTIME_FUNCTION(RuntimeHidden_Interrupt) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
return Execution::HandleStackGuardInterrupt(isolate);
@@ -9527,7 +9587,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
+RUNTIME_FUNCTION(Runtime_TraceEnter) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
PrintTransition(isolate, NULL);
@@ -9535,14 +9595,16 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
+RUNTIME_FUNCTION(Runtime_TraceExit) {
SealHandleScope shs(isolate);
- PrintTransition(isolate, args[0]);
- return args[0]; // return TOS
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_CHECKED(Object, obj, 0);
+ PrintTransition(isolate, obj);
+ return obj; // return TOS
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
+RUNTIME_FUNCTION(Runtime_DebugPrint) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -9573,7 +9635,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
+RUNTIME_FUNCTION(Runtime_DebugTrace) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
isolate->PrintStack(stdout);
@@ -9581,8 +9643,8 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DateCurrentTime) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 0);
// According to ECMA-262, section 15.9.1, page 117, the precision of
@@ -9590,11 +9652,11 @@
// time is milliseconds. Therefore, we floor the result of getting
// the OS time.
double millis = std::floor(OS::TimeCurrentMillis());
- return isolate->heap()->NumberFromDouble(millis);
+ return *isolate->factory()->NewNumber(millis);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
+RUNTIME_FUNCTION(Runtime_DateParseString) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
@@ -9629,29 +9691,31 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DateLocalTimezone) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
const char* zone =
isolate->date_cache()->LocalTimezone(static_cast<int64_t>(x));
- return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
+ Handle<String> result = isolate->factory()->NewStringFromUtf8(
+ CStrVector(zone)).ToHandleChecked();
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DateToUTC) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
- return isolate->heap()->NumberFromDouble(static_cast<double>(time));
+ return *isolate->factory()->NewNumber(static_cast<double>(time));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCacheVersion) {
+RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
HandleScope hs(isolate);
ASSERT(args.length() == 0);
if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
@@ -9672,28 +9736,28 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
+RUNTIME_FUNCTION(Runtime_GlobalReceiver) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* global = args[0];
+ CONVERT_ARG_CHECKED(Object, global, 0);
if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
return JSGlobalObject::cast(global)->global_receiver();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAttachedGlobal) {
+RUNTIME_FUNCTION(Runtime_IsAttachedGlobal) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* global = args[0];
+ CONVERT_ARG_CHECKED(Object, global, 0);
if (!global->IsJSGlobalObject()) return isolate->heap()->false_value();
return isolate->heap()->ToBoolean(
!JSGlobalObject::cast(global)->IsDetached());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
+RUNTIME_FUNCTION(Runtime_ParseJson) {
HandleScope scope(isolate);
- ASSERT_EQ(1, args.length());
+ ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
source = String::Flatten(source);
@@ -9724,9 +9788,9 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
+RUNTIME_FUNCTION(Runtime_CompileString) {
HandleScope scope(isolate);
- ASSERT_EQ(2, args.length());
+ ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
@@ -9746,9 +9810,11 @@
// Compile source string in the native context.
ParseRestriction restriction = function_literal_only
? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
- Handle<JSFunction> fun = Compiler::GetFunctionFromEval(
- source, context, SLOPPY, restriction, RelocInfo::kNoPosition);
- RETURN_IF_EMPTY_HANDLE(isolate, fun);
+ Handle<JSFunction> fun;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, fun,
+ Compiler::GetFunctionFromEval(
+ source, context, SLOPPY, restriction, RelocInfo::kNoPosition));
return *fun;
}
@@ -9769,21 +9835,23 @@
native_context->ErrorMessageForCodeGenerationFromStrings();
isolate->Throw(*isolate->factory()->NewEvalError(
"code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
- return MakePair(Failure::Exception(), NULL);
+ return MakePair(isolate->heap()->exception(), NULL);
}
// Deal with a normal eval call with a string argument. Compile it
// and return the compiled function bound in the local context.
static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
- Handle<JSFunction> compiled = Compiler::GetFunctionFromEval(
- source, context, strict_mode, restriction, scope_position);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, compiled,
- MakePair(Failure::Exception(), NULL));
+ Handle<JSFunction> compiled;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, compiled,
+ Compiler::GetFunctionFromEval(
+ source, context, strict_mode, restriction, scope_position),
+ MakePair(isolate->heap()->exception(), NULL));
return MakePair(*compiled, *receiver);
}
-RUNTIME_FUNCTION(ObjectPair, RuntimeHidden_ResolvePossiblyDirectEval) {
+RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_ResolvePossiblyDirectEval) {
HandleScope scope(isolate);
ASSERT(args.length() == 5);
@@ -9811,52 +9879,35 @@
}
-// Allocate a block of memory in the given space (filled with a filler).
-// Used as a fall-back for generated code when the space is full.
-static MaybeObject* Allocate(Isolate* isolate,
- int size,
- bool double_align,
- AllocationSpace space) {
- Heap* heap = isolate->heap();
+RUNTIME_FUNCTION(RuntimeHidden_AllocateInNewSpace) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_SMI_ARG_CHECKED(size, 0);
RUNTIME_ASSERT(IsAligned(size, kPointerSize));
RUNTIME_ASSERT(size > 0);
RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
- HeapObject* allocation;
- { MaybeObject* maybe_allocation = heap->AllocateRaw(size, space, space);
- if (!maybe_allocation->To(&allocation)) return maybe_allocation;
- }
-#ifdef DEBUG
- MemoryChunk* chunk = MemoryChunk::FromAddress(allocation->address());
- ASSERT(chunk->owner()->identity() == space);
-#endif
- heap->CreateFillerObjectAt(allocation->address(), size);
- return allocation;
+ return *isolate->factory()->NewFillerObject(size, false, NEW_SPACE);
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_AllocateInNewSpace) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 1);
- CONVERT_SMI_ARG_CHECKED(size, 0);
- return Allocate(isolate, size, false, NEW_SPACE);
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_AllocateInTargetSpace) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_AllocateInTargetSpace) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(size, 0);
CONVERT_SMI_ARG_CHECKED(flags, 1);
+ RUNTIME_ASSERT(IsAligned(size, kPointerSize));
+ RUNTIME_ASSERT(size > 0);
+ RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
bool double_align = AllocateDoubleAlignFlag::decode(flags);
AllocationSpace space = AllocateTargetSpace::decode(flags);
- return Allocate(isolate, size, double_align, space);
+ return *isolate->factory()->NewFillerObject(size, double_align, space);
}
// Push an object unto an array of objects if it is not already in the
// array. Returns true if the element was pushed on the stack and
// false otherwise.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
+RUNTIME_FUNCTION(Runtime_PushIfAbsent) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
@@ -10364,7 +10415,7 @@
* TODO(581): Fix non-compliance for very large concatenations and update to
* following the ECMAScript 5 specification.
*/
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
+RUNTIME_FUNCTION(Runtime_ArrayConcat) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 1);
@@ -10520,7 +10571,7 @@
if (obj->IsJSArray()) {
Handle<JSArray> array = Handle<JSArray>::cast(obj);
if (!IterateElements(isolate, array, &visitor)) {
- return Failure::Exception();
+ return isolate->heap()->exception();
}
} else {
visitor.visit(0, obj);
@@ -10539,7 +10590,7 @@
// This will not allocate (flatten the string), but it may run
// very slowly for very deeply nested ConsStrings. For debugging use only.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
+RUNTIME_FUNCTION(Runtime_GlobalPrint) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -10560,7 +10611,7 @@
// property.
// Returns the number of non-undefined elements collected.
// Returns -1 if hole removal is not supported by this method.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
+RUNTIME_FUNCTION(Runtime_RemoveArrayHoles) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@@ -10570,7 +10621,7 @@
// Move contents of argument 0 (an array) to argument 1 (an array)
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
+RUNTIME_FUNCTION(Runtime_MoveArrayContents) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, from, 0);
@@ -10593,7 +10644,7 @@
// How many elements does this object/array have?
-RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
+RUNTIME_FUNCTION(Runtime_EstimateNumberOfElements) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSObject, object, 0);
@@ -10614,7 +10665,7 @@
// or undefined) or a number representing the positive length of an interval
// starting at index 0.
// Intervals can span over some keys that are not in the object.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
+RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
@@ -10653,7 +10704,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
+RUNTIME_FUNCTION(Runtime_LookupAccessor) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
@@ -10661,15 +10712,16 @@
CONVERT_SMI_ARG_CHECKED(flag, 2);
AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
- Handle<Object> result =
- JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component));
return *result;
}
#ifdef ENABLE_DEBUGGER_SUPPORT
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
+RUNTIME_FUNCTION(Runtime_DebugBreak) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
return Execution::DebugBreakHelper(isolate);
@@ -10692,21 +10744,21 @@
// args[0]: debug event listener function to set or null or undefined for
// clearing the event listener function
// args[1]: object supplied during callback
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
+RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
RUNTIME_ASSERT(args[0]->IsJSFunction() ||
args[0]->IsUndefined() ||
args[0]->IsNull());
- Handle<Object> callback = args.at<Object>(0);
- Handle<Object> data = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
isolate->debugger()->SetEventListener(callback, data);
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
+RUNTIME_FUNCTION(Runtime_Break) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
isolate->stack_guard()->DebugBreak();
@@ -10772,7 +10824,7 @@
// 4: Setter function if defined
// Items 2-4 are only filled if the property has either a getter or a setter
// defined through __defineGetter__ and/or __defineSetter__.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
+RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -10862,7 +10914,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
+RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -10878,7 +10930,7 @@
// Return the property type calculated from the property details.
// args[0]: smi with property details.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
+RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
@@ -10888,7 +10940,7 @@
// Return the property attribute calculated from the property details.
// args[0]: smi with property details.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
+RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
@@ -10898,7 +10950,7 @@
// Return the property insertion index calculated from the property details.
// args[0]: smi with property details.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
+RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
@@ -10910,7 +10962,7 @@
// Return property value from named interceptor.
// args[0]: object
// args[1]: property name
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
+RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
@@ -10929,7 +10981,7 @@
// Return element value from indexed interceptor.
// args[0]: object
// args[1]: index
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
+RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
@@ -10942,31 +10994,26 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() >= 1);
- CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
- // Check that the break id is valid.
- if (isolate->debug()->break_id() == 0 ||
- break_id != isolate->debug()->break_id()) {
- return isolate->Throw(
- isolate->heap()->illegal_execution_state_string());
- }
+static bool CheckExecutionState(Isolate* isolate, int break_id) {
+ return (isolate->debug()->break_id() != 0 &&
+ break_id == isolate->debug()->break_id());
+}
+
+RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
+ SealHandleScope shs(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
return isolate->heap()->true_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
+RUNTIME_FUNCTION(Runtime_GetFrameCount) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
-
- // Check arguments.
- Object* result;
- { MaybeObject* maybe_result = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
// Count all frames which are relevant to debugging stack trace.
int n = 0;
@@ -11100,16 +11147,12 @@
// Arguments name, value
// Locals name, value
// Return value if any
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
+RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
Heap* heap = isolate->heap();
@@ -11157,33 +11200,44 @@
ASSERT(*scope_info != ScopeInfo::Empty(isolate));
// Get the locals names and values into a temporary array.
- //
- // TODO(1240907): Hide compiler-introduced stack variables
- // (e.g. .result)? For users of the debugger, they will probably be
- // confusing.
+ int local_count = scope_info->LocalCount();
+ for (int slot = 0; slot < scope_info->LocalCount(); ++slot) {
+ // Hide compiler-introduced temporary variables, whether on the stack or on
+ // the context.
+ if (scope_info->LocalIsSynthetic(slot))
+ local_count--;
+ }
+
Handle<FixedArray> locals =
- isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
+ isolate->factory()->NewFixedArray(local_count * 2);
// Fill in the values of the locals.
+ int local = 0;
int i = 0;
for (; i < scope_info->StackLocalCount(); ++i) {
// Use the value from the stack.
- locals->set(i * 2, scope_info->LocalName(i));
- locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
+ if (scope_info->LocalIsSynthetic(i))
+ continue;
+ locals->set(local * 2, scope_info->LocalName(i));
+ locals->set(local * 2 + 1, frame_inspector.GetExpression(i));
+ local++;
}
- if (i < scope_info->LocalCount()) {
+ if (local < local_count) {
// Get the context containing declarations.
Handle<Context> context(
Context::cast(it.frame()->context())->declaration_context());
for (; i < scope_info->LocalCount(); ++i) {
+ if (scope_info->LocalIsSynthetic(i))
+ continue;
Handle<String> name(scope_info->LocalName(i));
VariableMode mode;
InitializationFlag init_flag;
- locals->set(i * 2, *name);
+ locals->set(local * 2, *name);
int context_slot_index =
scope_info->ContextSlotIndex(*name, &mode, &init_flag);
Object* value = context->get(context_slot_index);
- locals->set(i * 2 + 1, value);
+ locals->set(local * 2 + 1, value);
+ local++;
}
}
@@ -11244,7 +11298,7 @@
// Calculate the size of the result.
int details_size = kFrameDetailsFirstDynamicIndex +
- 2 * (argument_count + scope_info->LocalCount()) +
+ 2 * (argument_count + local_count) +
(at_return ? 1 : 0);
Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
@@ -11259,7 +11313,7 @@
// Add the locals count
details->set(kFrameDetailsLocalCountIndex,
- Smi::FromInt(scope_info->LocalCount()));
+ Smi::FromInt(local_count));
// Add the source position.
if (position != RelocInfo::kNoPosition) {
@@ -11310,7 +11364,7 @@
}
// Add locals name and value from the temporary copy from the function frame.
- for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
+ for (int i = 0; i < local_count * 2; i++) {
details->set(details_index++, locals->get(i));
}
@@ -11391,6 +11445,7 @@
// Second fill all stack locals.
for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
+ if (scope_info->LocalIsSynthetic(i)) continue;
Handle<String> name(scope_info->StackLocalName(i));
Handle<Object> value(frame_inspector->GetExpression(i), isolate);
if (value->IsTheHole()) continue;
@@ -11435,6 +11490,7 @@
// Stack locals.
for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
+ if (scope_info->LocalIsSynthetic(i)) continue;
if (frame->GetExpression(i)->IsTheHole()) continue;
HandleScope scope(isolate);
Handle<Object> value = Object::GetPropertyOrElement(
@@ -11472,7 +11528,9 @@
Handle<JSObject> ext(JSObject::cast(function_context->extension()));
Handle<FixedArray> keys;
ASSIGN_RETURN_ON_EXCEPTION(
- isolate, keys, GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS), JSObject);
+ isolate, keys,
+ JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS),
+ JSObject);
for (int i = 0; i < keys->length(); i++) {
// Names of variables introduced by eval are strings.
@@ -11627,7 +11685,8 @@
Handle<JSObject> ext(JSObject::cast(context->extension()));
Handle<FixedArray> keys;
ASSIGN_RETURN_ON_EXCEPTION(
- isolate, keys, GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS), JSObject);
+ isolate, keys,
+ JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS), JSObject);
for (int i = 0; i < keys->length(); i++) {
HandleScope scope(isolate);
@@ -12127,16 +12186,12 @@
};
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
+RUNTIME_FUNCTION(Runtime_GetScopeCount) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
// Get the frame where the debugging is performed.
@@ -12159,16 +12214,12 @@
// Returns the list of step-in positions (text offset) in a function of the
// stack frame in a range from the current debug break position to the end
// of the corresponding statement.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
+RUNTIME_FUNCTION(Runtime_GetStepInPositions) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
// Get the frame where the debugging is performed.
@@ -12270,16 +12321,12 @@
// The array returned contains the following information:
// 0: Scope type
// 1: Scope object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
+RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
@@ -12314,16 +12361,12 @@
// The array returned contains arrays with the following information:
// 0: Scope type
// 1: Scope object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAllScopesDetails) {
+RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 3 || args.length() == 4);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
@@ -12355,7 +12398,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
+RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -12372,7 +12415,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
+RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -12393,7 +12436,6 @@
Handle<JSObject> details;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, details, MaterializeScopeDetails(isolate, &it));
- RETURN_IF_EMPTY_HANDLE(isolate, details);
return *details;
}
@@ -12420,22 +12462,20 @@
// args[5]: object: new value
//
// Return true if success and false otherwise
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) {
+RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
HandleScope scope(isolate);
ASSERT(args.length() == 6);
// Check arguments.
CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
- Handle<Object> new_value = args.at<Object>(5);
+ CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
bool res;
if (args[0]->IsNumber()) {
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
+
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
@@ -12456,7 +12496,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
+RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
@@ -12474,16 +12514,11 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
+RUNTIME_FUNCTION(Runtime_GetThreadCount) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
-
- // Check arguments.
- Object* result;
- { MaybeObject* maybe_result = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
// Count all archived V8 threads.
int n = 0;
@@ -12510,16 +12545,12 @@
// The array returned contains the following information:
// 0: Is current thread?
// 1: Thread id
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
+RUNTIME_FUNCTION(Runtime_GetThreadDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
// Allocate array for result.
@@ -12560,7 +12591,7 @@
// Sets the disable break state
// args[0]: disable break state
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
+RUNTIME_FUNCTION(Runtime_SetDisableBreak) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
@@ -12574,7 +12605,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
+RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -12602,13 +12633,13 @@
// args[0]: function
// args[1]: number: break source position (within the function source)
// args[2]: number: break point object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
+RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
RUNTIME_ASSERT(source_position >= 0);
- Handle<Object> break_point_object_arg = args.at<Object>(2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
// Set break point.
isolate->debug()->SetBreakPoint(function, break_point_object_arg,
@@ -12625,14 +12656,14 @@
// args[1]: number: break source position (within the script source)
// args[2]: number, breakpoint position alignment
// args[3]: number: break point object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
+RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
RUNTIME_ASSERT(source_position >= 0);
CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
- Handle<Object> break_point_object_arg = args.at<Object>(3);
+ CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
return isolate->ThrowIllegalOperation();
@@ -12657,10 +12688,10 @@
// Clear a break point
// args[0]: number: break point object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
+RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- Handle<Object> break_point_object_arg = args.at<Object>(0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
// Clear break point.
isolate->debug()->ClearBreakPoint(break_point_object_arg);
@@ -12672,16 +12703,15 @@
// Change the state of break on exceptions.
// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
// args[1]: Boolean indicating on/off.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
+RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
- RUNTIME_ASSERT(args[0]->IsNumber());
+ CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
// If the number doesn't match an enum value, the ChangeBreakOnException
// function will default to affecting caught exceptions.
- ExceptionBreakType type =
- static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
+ ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
// Update break point state.
isolate->debug()->ChangeBreakOnException(type, enable);
return isolate->heap()->undefined_value();
@@ -12690,13 +12720,12 @@
// Returns the state of break on exceptions
// args[0]: boolean indicating uncaught exceptions
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
+RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- RUNTIME_ASSERT(args[0]->IsNumber());
+ CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
- ExceptionBreakType type =
- static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
+ ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
bool result = isolate->debug()->IsBreakOnException(type);
return Smi::FromInt(result);
}
@@ -12707,15 +12736,12 @@
// args[1]: step action from the enumeration StepAction
// args[2]: number of times to perform the step, for step out it is the number
// of frames to step down.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
+RUNTIME_FUNCTION(Runtime_PrepareStep) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
+
if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
return isolate->Throw(isolate->heap()->illegal_argument_string());
}
@@ -12762,7 +12788,7 @@
// Clear all stepping set by PrepareStep.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
+RUNTIME_FUNCTION(Runtime_ClearStepping) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
isolate->debug()->ClearStepping();
@@ -12798,29 +12824,32 @@
// Compile and evaluate source for the given context.
-static MaybeObject* DebugEvaluate(Isolate* isolate,
- Handle<Context> context,
- Handle<Object> context_extension,
- Handle<Object> receiver,
- Handle<String> source) {
+static MaybeHandle<Object> DebugEvaluate(Isolate* isolate,
+ Handle<Context> context,
+ Handle<Object> context_extension,
+ Handle<Object> receiver,
+ Handle<String> source) {
if (context_extension->IsJSObject()) {
Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
Handle<JSFunction> closure(context->closure(), isolate);
context = isolate->factory()->NewWithContext(closure, context, extension);
}
- Handle<JSFunction> eval_fun =
+ Handle<JSFunction> eval_fun;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, eval_fun,
Compiler::GetFunctionFromEval(source,
context,
SLOPPY,
NO_PARSE_RESTRICTION,
- RelocInfo::kNoPosition);
- RETURN_IF_EMPTY_HANDLE(isolate, eval_fun);
+ RelocInfo::kNoPosition),
+ Object);
Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
- Execution::Call(isolate, eval_fun, receiver, 0, NULL));
+ Execution::Call(isolate, eval_fun, receiver, 0, NULL),
+ Object);
// Skip the global proxy as it has no properties and always delegates to the
// real global object.
@@ -12830,7 +12859,7 @@
// Clear the oneshot breakpoints so that the debugger does not step further.
isolate->debug()->ClearStepping();
- return *result;
+ return result;
}
@@ -12839,22 +12868,20 @@
// - Parameters and stack-allocated locals need to be materialized. Altered
// values need to be written back to the stack afterwards.
// - The arguments object needs to materialized.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
+RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
HandleScope scope(isolate);
// Check the execution state and decode arguments frame and source to be
// evaluated.
ASSERT(args.length() == 6);
- Object* check_result;
- { MaybeObject* maybe_result = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_result->ToObject(&check_result)) return maybe_result;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
+
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
- Handle<Object> context_extension(args[5], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 5);
// Handle the processing of break.
DisableBreak disable_break_save(isolate, disable_break);
@@ -12894,13 +12921,10 @@
context = isolate->factory()->NewWithContext(function, context, materialized);
Handle<Object> receiver(frame->receiver(), isolate);
- Object* evaluate_result_object;
- { MaybeObject* maybe_result =
- DebugEvaluate(isolate, context, context_extension, receiver, source);
- if (!maybe_result->ToObject(&evaluate_result_object)) return maybe_result;
- }
-
- Handle<Object> result(evaluate_result_object, isolate);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ DebugEvaluate(isolate, context, context_extension, receiver, source));
// Write back potential changes to materialized stack locals to the stack.
UpdateStackLocalsFromMaterializedObject(
@@ -12910,20 +12934,18 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
+RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
HandleScope scope(isolate);
// Check the execution state and decode arguments frame and source to be
// evaluated.
ASSERT(args.length() == 4);
- Object* check_result;
- { MaybeObject* maybe_result = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_result->ToObject(&check_result)) return maybe_result;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
+
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
- Handle<Object> context_extension(args[3], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 3);
// Handle the processing of break.
DisableBreak disable_break_save(isolate, disable_break);
@@ -12942,11 +12964,15 @@
// debugger was invoked.
Handle<Context> context = isolate->native_context();
Handle<Object> receiver = isolate->global_object();
- return DebugEvaluate(isolate, context, context_extension, receiver, source);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ DebugEvaluate(isolate, context, context_extension, receiver, source));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
+RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
@@ -12961,7 +12987,7 @@
// instances->set(i, *GetScriptWrapper(script))
// is unsafe as GetScriptWrapper might call GC and the C++ compiler might
// already have dereferenced the instances handle.
- Handle<JSValue> wrapper = GetScriptWrapper(script);
+ Handle<JSObject> wrapper = Script::GetWrapper(script);
instances->set(i, *wrapper);
}
@@ -13048,7 +13074,7 @@
// args[0]: the object to find references to
// args[1]: constructor function for instances to exclude (Mirror)
// args[2]: the the maximum number of objects to return
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
+RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -13062,7 +13088,7 @@
// Check parameters.
CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
- Handle<Object> instance_filter = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1);
RUNTIME_ASSERT(instance_filter->IsUndefined() ||
instance_filter->IsJSObject());
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
@@ -13138,7 +13164,7 @@
// Scan the heap for objects constructed by a specific function.
// args[0]: the constructor to find instances of
// args[1]: the the maximum number of objects to return
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
+RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -13183,16 +13209,16 @@
// Find the effective prototype object as returned by __proto__.
// args[0]: the object to find the prototype for.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
+ HandleScope shs(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(JSObject, obj, 0);
- return GetPrototypeSkipHiddenPrototypes(isolate, obj);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
+ return *GetPrototypeSkipHiddenPrototypes(isolate, obj);
}
// Patches script source (should be called upon BeforeCompile event).
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
+RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -13210,7 +13236,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
+RUNTIME_FUNCTION(Runtime_SystemBreak) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
OS::DebugBreak();
@@ -13218,14 +13244,14 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
+RUNTIME_FUNCTION(Runtime_DebugDisassembleFunction) {
HandleScope scope(isolate);
#ifdef DEBUG
ASSERT(args.length() == 1);
// Get the function and make sure it is compiled.
CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
- return Failure::Exception();
+ return isolate->heap()->exception();
}
func->code()->PrintLn();
#endif // DEBUG
@@ -13233,14 +13259,14 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
+RUNTIME_FUNCTION(Runtime_DebugDisassembleConstructor) {
HandleScope scope(isolate);
#ifdef DEBUG
ASSERT(args.length() == 1);
// Get the function and make sure it is compiled.
CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
- return Failure::Exception();
+ return isolate->heap()->exception();
}
func->shared()->construct_stub()->PrintLn();
#endif // DEBUG
@@ -13248,7 +13274,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
+RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -13286,8 +13312,7 @@
// For a script finds all SharedFunctionInfo's in the heap that points
// to this script. Returns JSArray of SharedFunctionInfo wrapped
// in OpaqueReferences.
-RUNTIME_FUNCTION(MaybeObject*,
- Runtime_LiveEditFindSharedFunctionInfosForScript) {
+RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 1);
@@ -13336,7 +13361,7 @@
// Returns a JSArray of compilation infos. The array is ordered so that
// each function with all its descendant is always stored in a continues range
// with the function itself going first. The root function is a script function.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
+RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 2);
@@ -13356,13 +13381,13 @@
// Changes the source of the script to a new_source.
// If old_script_name is provided (i.e. is a String), also creates a copy of
// the script with its original source and sends notification to debugger.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
+RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 3);
CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
- Handle<Object> old_script_name(args[2], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, old_script_name, 2);
RUNTIME_ASSERT(original_script_value->value()->IsScript());
Handle<Script> original_script(Script::cast(original_script_value->value()));
@@ -13372,14 +13397,14 @@
if (old_script->IsScript()) {
Handle<Script> script_handle = Handle<Script>::cast(old_script);
- return *(GetScriptWrapper(script_handle));
+ return *Script::GetWrapper(script_handle);
} else {
return isolate->heap()->null_value();
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
+RUNTIME_FUNCTION(Runtime_LiveEditFunctionSourceUpdated) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 1);
@@ -13392,7 +13417,7 @@
// Replaces code of SharedFunctionInfo with a new one.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
+RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 2);
@@ -13406,12 +13431,12 @@
// Connects SharedFunctionInfo to another script.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
+RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 2);
- Handle<Object> function_object(args[0], isolate);
- Handle<Object> script_object(args[1], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, script_object, 1);
if (function_object->IsJSValue()) {
Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
@@ -13433,7 +13458,7 @@
// In a code of a parent function replaces original function as embedded object
// with a substitution one.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
+RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 3);
@@ -13453,7 +13478,7 @@
// array of groups of 3 numbers:
// (change_begin, change_end, change_end_new_position).
// Each group describes a change in text; groups are sorted by change_begin.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
+RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 2);
@@ -13470,7 +13495,7 @@
// checks that none of them have activations on stacks (of any thread).
// Returns array of the same length with corresponding results of
// LiveEdit::FunctionPatchabilityStatus type.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
+RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 2);
@@ -13484,7 +13509,7 @@
// Compares 2 strings line-by-line, then token-wise and returns diff in form
// of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
// of diff chunks.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
+RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 2);
@@ -13497,17 +13522,13 @@
// Restarts a call frame and completely drops all frames above.
// Returns true if successful. Otherwise returns undefined or an error message.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
+RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
Heap* heap = isolate->heap();
@@ -13536,7 +13557,7 @@
// A testing entry. Returns statement position which is the closest to
// source_position.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
+RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {
HandleScope scope(isolate);
CHECK(isolate->debugger()->live_edit_enabled());
ASSERT(args.length() == 2);
@@ -13574,7 +13595,7 @@
// Calls specified function with or without entering the debugger.
// This is used in unit tests to run code as if debugger is entered or simply
// to have a stack with C++ frame in the middle.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
+RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -13602,8 +13623,9 @@
// Sets a v8 flag.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
+RUNTIME_FUNCTION(Runtime_SetFlags) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(String, arg, 0);
SmartArrayPointer<char> flags =
arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
@@ -13614,16 +13636,18 @@
// Performs a GC.
// Presently, it only does a full GC.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
+RUNTIME_FUNCTION(Runtime_CollectGarbage) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 1);
isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
return isolate->heap()->undefined_value();
}
// Gets the current heap usage.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
+RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 0);
int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
if (!Smi::IsValid(usage)) {
return *isolate->factory()->NewNumberFromInt(usage);
@@ -13635,8 +13659,9 @@
#ifdef V8_I18N_SUPPORT
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
+RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) {
HandleScope scope(isolate);
+ Factory* factory = isolate->factory();
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
@@ -13653,7 +13678,7 @@
uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &error);
if (U_FAILURE(error) || icu_length == 0) {
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
+ return *factory->NewStringFromAsciiChecked(kInvalidTag);
}
char result[ULOC_FULLNAME_CAPACITY];
@@ -13662,15 +13687,16 @@
uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
if (U_FAILURE(error)) {
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
+ return *factory->NewStringFromAsciiChecked(kInvalidTag);
}
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
+ return *factory->NewStringFromAsciiChecked(result);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
+RUNTIME_FUNCTION(Runtime_AvailableLocalesOf) {
HandleScope scope(isolate);
+ Factory* factory = isolate->factory();
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
@@ -13691,7 +13717,7 @@
UErrorCode error = U_ZERO_ERROR;
char result[ULOC_FULLNAME_CAPACITY];
Handle<JSObject> locales =
- isolate->factory()->NewJSObject(isolate->object_function());
+ factory->NewJSObject(isolate->object_function());
for (int32_t i = 0; i < count; ++i) {
const char* icu_name = available_locales[i].getName();
@@ -13704,11 +13730,11 @@
continue;
}
- RETURN_IF_EMPTY_HANDLE(isolate,
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
locales,
- isolate->factory()->NewStringFromAscii(CStrVector(result)),
- isolate->factory()->NewNumber(i),
+ factory->NewStringFromAsciiChecked(result),
+ factory->NewNumber(i),
NONE));
}
@@ -13716,8 +13742,9 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) {
+ HandleScope scope(isolate);
+ Factory* factory = isolate->factory();
ASSERT(args.length() == 0);
@@ -13729,32 +13756,31 @@
uloc_toLanguageTag(
default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
if (U_SUCCESS(status)) {
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
+ return *factory->NewStringFromAsciiChecked(result);
}
- return isolate->heap()->AllocateStringFromOneByte(CStrVector("und"));
+ return *factory->NewStringFromStaticAscii("und");
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
+RUNTIME_FUNCTION(Runtime_GetLanguageTagVariants) {
HandleScope scope(isolate);
+ Factory* factory = isolate->factory();
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
uint32_t length = static_cast<uint32_t>(input->length()->Number());
- Handle<FixedArray> output = isolate->factory()->NewFixedArray(length);
- Handle<Name> maximized =
- isolate->factory()->NewStringFromAscii(CStrVector("maximized"));
- Handle<Name> base =
- isolate->factory()->NewStringFromAscii(CStrVector("base"));
+ Handle<FixedArray> output = factory->NewFixedArray(length);
+ Handle<Name> maximized = factory->NewStringFromStaticAscii("maximized");
+ Handle<Name> base = factory->NewStringFromStaticAscii("base");
for (unsigned int i = 0; i < length; ++i) {
Handle<Object> locale_id;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, locale_id, Object::GetElement(isolate, input, i));
if (!locale_id->IsString()) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
+ return isolate->Throw(*factory->illegal_argument_string());
}
v8::String::Utf8Value utf8_locale_id(
@@ -13769,7 +13795,7 @@
uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
&icu_locale_length, &error);
if (U_FAILURE(error) || icu_locale_length == 0) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
+ return isolate->Throw(*factory->illegal_argument_string());
}
// Maximize the locale.
@@ -13802,40 +13828,39 @@
icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
if (U_FAILURE(error)) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
+ return isolate->Throw(*factory->illegal_argument_string());
}
- Handle<JSObject> result =
- isolate->factory()->NewJSObject(isolate->object_function());
- RETURN_IF_EMPTY_HANDLE(isolate,
+ Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
result,
maximized,
- isolate->factory()->NewStringFromAscii(CStrVector(base_max_locale)),
+ factory->NewStringFromAsciiChecked(base_max_locale),
NONE));
- RETURN_IF_EMPTY_HANDLE(isolate,
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
result,
base,
- isolate->factory()->NewStringFromAscii(CStrVector(base_locale)),
+ factory->NewStringFromAsciiChecked(base_locale),
NONE));
output->set(i, *result);
}
- Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(output);
+ Handle<JSArray> result = factory->NewJSArrayWithElements(output);
result->set_length(Smi::FromInt(length));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInitializedIntlObject) {
+RUNTIME_FUNCTION(Runtime_IsInitializedIntlObject) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
- if (!input->IsJSObject()) return isolate->heap()->ToBoolean(false);
+ if (!input->IsJSObject()) return isolate->heap()->false_value();
Handle<JSObject> obj = Handle<JSObject>::cast(input);
Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
@@ -13844,7 +13869,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInitializedIntlObjectOfType) {
+RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -13852,7 +13877,7 @@
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
CONVERT_ARG_HANDLE_CHECKED(String, expected_type, 1);
- if (!input->IsJSObject()) return isolate->heap()->ToBoolean(false);
+ if (!input->IsJSObject()) return isolate->heap()->false_value();
Handle<JSObject> obj = Handle<JSObject>::cast(input);
Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
@@ -13862,7 +13887,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MarkAsInitializedIntlObjectOfType) {
+RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -13881,7 +13906,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetImplFromInitializedIntlObject) {
+RUNTIME_FUNCTION(Runtime_GetImplFromInitializedIntlObject) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -13909,7 +13934,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
+RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -13935,11 +13960,11 @@
local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
- RETURN_IF_EMPTY_HANDLE(isolate,
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
+ isolate->factory()->NewStringFromStaticAscii("dateFormat"),
+ isolate->factory()->NewStringFromStaticAscii("valid"),
NONE));
// Make object handle weak so we can delete the data format once GC kicks in.
@@ -13951,7 +13976,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
+RUNTIME_FUNCTION(Runtime_InternalDateFormat) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -13970,14 +13995,18 @@
icu::UnicodeString result;
date_format->format(value->Number(), result);
- return *isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(result.getBuffer()),
- result.length()));
+ Handle<String> result_str;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result_str,
+ isolate->factory()->NewStringFromTwoByte(
+ Vector<const uint16_t>(
+ reinterpret_cast<const uint16_t*>(result.getBuffer()),
+ result.length())));
+ return *result_str;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
+RUNTIME_FUNCTION(Runtime_InternalDateParse) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -14004,7 +14033,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
+RUNTIME_FUNCTION(Runtime_CreateNumberFormat) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -14030,11 +14059,11 @@
local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
- RETURN_IF_EMPTY_HANDLE(isolate,
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
+ isolate->factory()->NewStringFromStaticAscii("numberFormat"),
+ isolate->factory()->NewStringFromStaticAscii("valid"),
NONE));
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
@@ -14045,7 +14074,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
+RUNTIME_FUNCTION(Runtime_InternalNumberFormat) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -14064,14 +14093,18 @@
icu::UnicodeString result;
number_format->format(value->Number(), result);
- return *isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(result.getBuffer()),
- result.length()));
+ Handle<String> result_str;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result_str,
+ isolate->factory()->NewStringFromTwoByte(
+ Vector<const uint16_t>(
+ reinterpret_cast<const uint16_t*>(result.getBuffer()),
+ result.length())));
+ return *result_str;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
+RUNTIME_FUNCTION(Runtime_InternalNumberParse) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -14110,7 +14143,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
+RUNTIME_FUNCTION(Runtime_CreateCollator) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -14134,11 +14167,11 @@
local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
- RETURN_IF_EMPTY_HANDLE(isolate,
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("collator")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
+ isolate->factory()->NewStringFromStaticAscii("collator"),
+ isolate->factory()->NewStringFromStaticAscii("valid"),
NONE));
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
@@ -14149,7 +14182,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
+RUNTIME_FUNCTION(Runtime_InternalCompare) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -14177,7 +14210,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringNormalize) {
+RUNTIME_FUNCTION(Runtime_StringNormalize) {
HandleScope scope(isolate);
static const UNormalizationMode normalizationForms[] =
{ UNORM_NFC, UNORM_NFD, UNORM_NFKC, UNORM_NFKD };
@@ -14199,14 +14232,18 @@
return isolate->heap()->undefined_value();
}
- return *isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(result.getBuffer()),
- result.length()));
+ Handle<String> result_str;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result_str,
+ isolate->factory()->NewStringFromTwoByte(
+ Vector<const uint16_t>(
+ reinterpret_cast<const uint16_t*>(result.getBuffer()),
+ result.length())));
+ return *result_str;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateBreakIterator) {
+RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -14234,11 +14271,11 @@
// Make sure that the pointer to adopted text is NULL.
local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
- RETURN_IF_EMPTY_HANDLE(isolate,
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("breakIterator")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
+ isolate->factory()->NewStringFromStaticAscii("breakIterator"),
+ isolate->factory()->NewStringFromStaticAscii("valid"),
NONE));
// Make object handle weak so we can delete the break iterator once GC kicks
@@ -14251,7 +14288,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorAdoptText) {
+RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -14278,7 +14315,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorFirst) {
+RUNTIME_FUNCTION(Runtime_BreakIteratorFirst) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -14293,7 +14330,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorNext) {
+RUNTIME_FUNCTION(Runtime_BreakIteratorNext) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -14308,7 +14345,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorCurrent) {
+RUNTIME_FUNCTION(Runtime_BreakIteratorCurrent) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -14323,7 +14360,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorBreakType) {
+RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -14340,17 +14377,17 @@
int32_t status = rule_based_iterator->getRuleStatus();
// Keep return values in sync with JavaScript BreakType enum.
if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
- return *isolate->factory()->NewStringFromAscii(CStrVector("none"));
+ return *isolate->factory()->NewStringFromStaticAscii("none");
} else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
- return *isolate->factory()->NewStringFromAscii(CStrVector("number"));
+ return *isolate->factory()->NewStringFromStaticAscii("number");
} else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
- return *isolate->factory()->NewStringFromAscii(CStrVector("letter"));
+ return *isolate->factory()->NewStringFromStaticAscii("letter");
} else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
- return *isolate->factory()->NewStringFromAscii(CStrVector("kana"));
+ return *isolate->factory()->NewStringFromStaticAscii("kana");
} else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
- return *isolate->factory()->NewStringFromAscii(CStrVector("ideo"));
+ return *isolate->factory()->NewStringFromStaticAscii("ideo");
} else {
- return *isolate->factory()->NewStringFromAscii(CStrVector("unknown"));
+ return *isolate->factory()->NewStringFromStaticAscii("unknown");
}
}
#endif // V8_I18N_SUPPORT
@@ -14388,14 +14425,14 @@
if (script.is_null()) return factory->undefined_value();
// Return the script found.
- return GetScriptWrapper(script);
+ return Script::GetWrapper(script);
}
// Get the script object from script data. NOTE: Regarding performance
// see the NOTE for GetScriptFromScriptData.
// args[0]: script data for the script to find the source for
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
+RUNTIME_FUNCTION(Runtime_GetScript) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -14412,11 +14449,11 @@
// Collect the raw data for a stack trace. Returns an array of 4
// element segments each containing a receiver, function, code and
// native code offset.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
+RUNTIME_FUNCTION(Runtime_CollectStackTrace) {
HandleScope scope(isolate);
- ASSERT_EQ(args.length(), 3);
+ ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
- Handle<Object> caller = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, caller, 1);
CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
// Optionally capture a more detailed stack trace for the message.
@@ -14428,9 +14465,9 @@
// Retrieve the stack trace. This is the raw stack trace that yet has to
// be formatted. Since we only need this once, clear it afterwards.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) {
+RUNTIME_FUNCTION(Runtime_GetAndClearOverflowedStackTrace) {
HandleScope scope(isolate);
- ASSERT_EQ(args.length(), 1);
+ ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
Handle<String> key = isolate->factory()->hidden_stack_trace_string();
Handle<Object> result(error_object->GetHiddenProperty(*key), isolate);
@@ -14442,18 +14479,17 @@
// Returns V8 version as a string.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
- SealHandleScope shs(isolate);
- ASSERT_EQ(args.length(), 0);
+RUNTIME_FUNCTION(Runtime_GetV8Version) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 0);
const char* version_string = v8::V8::GetVersion();
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(version_string),
- NOT_TENURED);
+ return *isolate->factory()->NewStringFromAsciiChecked(version_string);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
+RUNTIME_FUNCTION(Runtime_Abort) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_SMI_ARG_CHECKED(message_id, 0);
@@ -14467,7 +14503,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_AbortJS) {
+RUNTIME_FUNCTION(Runtime_AbortJS) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
@@ -14479,7 +14515,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FlattenString) {
+RUNTIME_FUNCTION(Runtime_FlattenString) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
@@ -14487,7 +14523,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyContextDisposed) {
+RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
isolate->heap()->NotifyContextDisposed();
@@ -14495,7 +14531,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LoadMutableDouble) {
+RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@@ -14508,7 +14544,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TryMigrateInstance) {
+RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
@@ -14525,37 +14561,41 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_GetFromCache) {
+RUNTIME_FUNCTION(RuntimeHidden_GetFromCache) {
SealHandleScope shs(isolate);
// This is only called from codegen, so checks might be more lax.
CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
- Object* key = args[1];
+ CONVERT_ARG_CHECKED(Object, key, 1);
- int finger_index = cache->finger_index();
- Object* o = cache->get(finger_index);
- if (o == key) {
- // The fastest case: hit the same place again.
- return cache->get(finger_index + 1);
- }
+ {
+ DisallowHeapAllocation no_alloc;
- for (int i = finger_index - 2;
- i >= JSFunctionResultCache::kEntriesIndex;
- i -= 2) {
- o = cache->get(i);
+ int finger_index = cache->finger_index();
+ Object* o = cache->get(finger_index);
if (o == key) {
- cache->set_finger_index(i);
- return cache->get(i + 1);
+ // The fastest case: hit the same place again.
+ return cache->get(finger_index + 1);
}
- }
- int size = cache->size();
- ASSERT(size <= cache->length());
+ for (int i = finger_index - 2;
+ i >= JSFunctionResultCache::kEntriesIndex;
+ i -= 2) {
+ o = cache->get(i);
+ if (o == key) {
+ cache->set_finger_index(i);
+ return cache->get(i + 1);
+ }
+ }
- for (int i = size - 2; i > finger_index; i -= 2) {
- o = cache->get(i);
- if (o == key) {
- cache->set_finger_index(i);
- return cache->get(i + 1);
+ int size = cache->size();
+ ASSERT(size <= cache->length());
+
+ for (int i = size - 2; i > finger_index; i -= 2) {
+ o = cache->get(i);
+ if (o == key) {
+ cache->set_finger_index(i);
+ return cache->get(i + 1);
+ }
}
}
@@ -14585,8 +14625,8 @@
#endif
// Function invocation may have cleared the cache. Reread all the data.
- finger_index = cache_handle->finger_index();
- size = cache_handle->size();
+ int finger_index = cache_handle->finger_index();
+ int size = cache_handle->size();
// If we have spare room, put new data into it, otherwise evict post finger
// entry which is likely to be the least recently used.
@@ -14619,15 +14659,17 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
+RUNTIME_FUNCTION(Runtime_MessageGetStartPosition) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
return Smi::FromInt(message->start_position());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
+RUNTIME_FUNCTION(Runtime_MessageGetScript) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
return message->script();
}
@@ -14636,7 +14678,7 @@
#ifdef DEBUG
// ListNatives is ONLY used by the fuzz-natives.js in debug mode
// Exclude the code in release mode.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
+RUNTIME_FUNCTION(Runtime_ListNatives) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
#define COUNT_ENTRY(Name, argc, ressize) + 1
@@ -14655,11 +14697,9 @@
Handle<String> name; \
/* Inline runtime functions have an underscore in front of the name. */ \
if (inline_runtime_functions) { \
- name = factory->NewStringFromAscii( \
- Vector<const char>("_" #Name, StrLength("_" #Name))); \
+ name = factory->NewStringFromStaticAscii("_" #Name); \
} else { \
- name = factory->NewStringFromAscii( \
- Vector<const char>(#Name, StrLength(#Name))); \
+ name = factory->NewStringFromStaticAscii(#Name); \
} \
Handle<FixedArray> pair_elements = factory->NewFixedArray(2); \
pair_elements->set(0, *name); \
@@ -14681,7 +14721,7 @@
#endif
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_Log) {
+RUNTIME_FUNCTION(RuntimeHidden_Log) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, format, 0);
@@ -14694,15 +14734,15 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
+RUNTIME_FUNCTION(Runtime_IS_VAR) {
UNREACHABLE(); // implemented as macro in the parser
return NULL;
}
#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
- RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \
- CONVERT_ARG_CHECKED(JSObject, obj, 0); \
+ RUNTIME_FUNCTION(Runtime_Has##Name) { \
+ CONVERT_ARG_CHECKED(JSObject, obj, 0); \
return isolate->heap()->ToBoolean(obj->Has##Name()); \
}
@@ -14721,7 +14761,7 @@
#define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \
- RUNTIME_FUNCTION(MaybeObject*, Runtime_HasExternal##Type##Elements) { \
+ RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \
CONVERT_ARG_CHECKED(JSObject, obj, 0); \
return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \
}
@@ -14732,7 +14772,7 @@
#define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
- RUNTIME_FUNCTION(MaybeObject*, Runtime_HasFixed##Type##Elements) { \
+ RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \
CONVERT_ARG_CHECKED(JSObject, obj, 0); \
return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
}
@@ -14742,7 +14782,7 @@
#undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
-RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
+RUNTIME_FUNCTION(Runtime_HaveSameMap) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(JSObject, obj1, 0);
@@ -14751,7 +14791,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessCheckNeeded) {
+RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(HeapObject, obj, 0);
@@ -14759,12 +14799,12 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
+RUNTIME_FUNCTION(Runtime_IsObserved) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
- JSReceiver* obj = JSReceiver::cast(args[0]);
+ CONVERT_ARG_CHECKED(JSReceiver, obj, 0);
if (obj->IsJSGlobalProxy()) {
Object* proto = obj->GetPrototype();
if (proto->IsNull()) return isolate->heap()->false_value();
@@ -14775,7 +14815,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
+RUNTIME_FUNCTION(Runtime_SetIsObserved) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
@@ -14794,7 +14834,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetMicrotaskPending) {
+RUNTIME_FUNCTION(Runtime_SetMicrotaskPending) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_BOOLEAN_ARG_CHECKED(new_state, 0);
@@ -14804,7 +14844,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RunMicrotasks) {
+RUNTIME_FUNCTION(Runtime_RunMicrotasks) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
if (isolate->microtask_pending()) Execution::RunMicrotasks(isolate);
@@ -14812,21 +14852,21 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetMicrotaskState) {
+RUNTIME_FUNCTION(Runtime_GetMicrotaskState) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
return isolate->heap()->microtask_state();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) {
+RUNTIME_FUNCTION(Runtime_GetObservationState) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
return isolate->heap()->observation_state();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
+RUNTIME_FUNCTION(Runtime_ObservationWeakMapCreate) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
// TODO(adamk): Currently this runtime function is only called three times per
@@ -14836,17 +14876,17 @@
isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
Handle<JSWeakMap> weakmap =
Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
- return WeakCollectionInitialize(isolate, weakmap);
+ return *WeakCollectionInitialize(isolate, weakmap);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) {
+RUNTIME_FUNCTION(Runtime_IsAccessAllowedForObserver) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
ASSERT(object->map()->is_access_check_needed());
- Handle<Object> key = args.at<Object>(2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
SaveContext save(isolate);
isolate->set_context(observer->context());
if (!isolate->MayNamedAccess(
@@ -14869,7 +14909,7 @@
}
-static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
+static Object* ArrayConstructorCommon(Isolate* isolate,
Handle<JSFunction> constructor,
Handle<AllocationSite> site,
Arguments* caller_args) {
@@ -14908,7 +14948,6 @@
Handle<Map> initial_map(constructor->initial_map(), isolate);
if (to_kind != initial_map->elements_kind()) {
initial_map = Map::AsElementsKind(initial_map, to_kind);
- RETURN_IF_EMPTY_HANDLE(isolate, initial_map);
}
// If we don't care to track arrays of to_kind ElementsKind, then
@@ -14948,7 +14987,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ArrayConstructor) {
+RUNTIME_FUNCTION(RuntimeHidden_ArrayConstructor) {
HandleScope scope(isolate);
// If we get 2 arguments then they are the stub parameters (constructor, type
// info). If we get 4, then the first one is a pointer to the arguments
@@ -14985,7 +15024,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_InternalArrayConstructor) {
+RUNTIME_FUNCTION(RuntimeHidden_InternalArrayConstructor) {
HandleScope scope(isolate);
Arguments empty_args(0, NULL);
bool no_caller_args = args.length() == 1;
@@ -15008,7 +15047,8 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MaxSmi) {
+RUNTIME_FUNCTION(Runtime_MaxSmi) {
+ ASSERT(args.length() == 0);
return Smi::FromInt(Smi::kMaxValue);
}
@@ -15083,31 +15123,4 @@
return &(kIntrinsicFunctions[static_cast<int>(id)]);
}
-
-void Runtime::PerformGC(Object* result, Isolate* isolate) {
- Failure* failure = Failure::cast(result);
- if (failure->IsRetryAfterGC()) {
- if (isolate->heap()->new_space()->AddFreshPage()) {
- return;
- }
-
- // Try to do a garbage collection; ignore it if it fails. The C
- // entry stub will throw an out-of-memory exception in that case.
- isolate->heap()->CollectGarbage(failure->allocation_space(),
- "Runtime::PerformGC");
- } else {
- // Handle last resort GC and make sure to allow future allocations
- // to grow the heap without causing GCs (if possible).
- isolate->counters()->gc_last_resort_from_js()->Increment();
- isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
- "Runtime::PerformGC");
- }
-}
-
-
-void Runtime::OutOfMemory() {
- Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true);
- UNREACHABLE();
-}
-
} } // namespace v8::internal
diff --git a/src/runtime.h b/src/runtime.h
index 1ae4972..237f9de 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -134,7 +134,6 @@
F(NumberDiv, 2, 1) \
F(NumberMod, 2, 1) \
F(NumberUnaryMinus, 1, 1) \
- F(NumberAlloc, 0, 1) \
F(NumberImul, 2, 1) \
\
F(StringBuilderConcat, 3, 1) \
@@ -298,15 +297,25 @@
F(SetAdd, 2, 1) \
F(SetHas, 2, 1) \
F(SetDelete, 2, 1) \
+ F(SetClear, 1, 1) \
F(SetGetSize, 1, 1) \
+ F(SetCreateIterator, 2, 1) \
+ \
+ F(SetIteratorNext, 1, 1) \
+ F(SetIteratorClose, 1, 1) \
\
/* Harmony maps */ \
F(MapInitialize, 1, 1) \
F(MapGet, 2, 1) \
F(MapHas, 2, 1) \
F(MapDelete, 2, 1) \
+ F(MapClear, 1, 1) \
F(MapSet, 3, 1) \
F(MapGetSize, 1, 1) \
+ F(MapCreateIterator, 2, 1) \
+ \
+ F(MapIteratorNext, 1, 1) \
+ F(MapIteratorClose, 1, 1) \
\
/* Harmony weak maps and sets */ \
F(WeakCollectionInitialize, 1, 1) \
@@ -891,10 +900,6 @@
ElementsKind* fixed_elements_kind,
size_t *element_size);
- // Helper functions used stubs.
- static void PerformGC(Object* result, Isolate* isolate);
- static void OutOfMemory();
-
// Used in runtime.cc and hydrogen's VisitArrayLiteral.
MUST_USE_RESULT static MaybeHandle<Object> CreateArrayLiteralBoilerplate(
Isolate* isolate,
diff --git a/src/runtime.js b/src/runtime.js
index a49bc84..7b83345 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -464,7 +464,7 @@
}
-function APPLY_OVERFLOW(length) {
+function STACK_OVERFLOW(length) {
throw %MakeRangeError('stack_overflow', []);
}
diff --git a/src/scanner.cc b/src/scanner.cc
index 67211e0..fe75010 100644
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -1118,13 +1118,19 @@
Handle<String> Scanner::AllocateNextLiteralString(Isolate* isolate,
PretenureFlag tenured) {
+ MaybeHandle<String> maybe_result;
if (is_next_literal_one_byte()) {
- return isolate->factory()->NewStringFromOneByte(
- Vector<const uint8_t>::cast(next_literal_one_byte_string()), tenured);
+ maybe_result = isolate->factory()->NewStringFromOneByte(
+ next_literal_one_byte_string(), tenured);
} else {
- return isolate->factory()->NewStringFromTwoByte(
- next_literal_two_byte_string(), tenured);
+ maybe_result = isolate->factory()->NewStringFromTwoByte(
+ next_literal_two_byte_string(), tenured);
}
+ // TODO(ishell): Temporarily returning null handle from here. I will proceed
+ // with maybehandlification in next CLs.
+ Handle<String> result;
+ if (!maybe_result.ToHandle(&result)) return Handle<String>();
+ return result;
}
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index 157cdfa..564565f 100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -278,6 +278,17 @@
}
+bool ScopeInfo::LocalIsSynthetic(int var) {
+ ASSERT(0 <= var && var < LocalCount());
+ // There's currently no flag stored on the ScopeInfo to indicate that a
+ // variable is a compiler-introduced temporary. However, to avoid conflict
+ // with user declarations, the current temporaries like .generator_object and
+ // .result start with a dot, so we can use that as a flag. It's a hack!
+ Handle<String> name(LocalName(var));
+ return name->length() > 0 && name->Get(0) == '.';
+}
+
+
int ScopeInfo::StackSlotIndex(String* name) {
ASSERT(name->IsInternalizedString());
if (length() > 0) {
@@ -368,16 +379,17 @@
int local_count = scope_info->ContextLocalCount();
if (local_count == 0) return true;
// Fill all context locals to the context extension.
+ int first_context_var = scope_info->StackLocalCount();
int start = scope_info->ContextLocalNameEntriesIndex();
- int end = start + local_count;
- for (int i = start; i < end; ++i) {
- int context_index = Context::MIN_CONTEXT_SLOTS + i - start;
+ for (int i = 0; i < local_count; ++i) {
+ if (scope_info->LocalIsSynthetic(first_context_var + i)) continue;
+ int context_index = Context::MIN_CONTEXT_SLOTS + i;
RETURN_ON_EXCEPTION_VALUE(
isolate,
Runtime::SetObjectProperty(
isolate,
scope_object,
- Handle<String>(String::cast(scope_info->get(i))),
+ Handle<String>(String::cast(scope_info->get(i + start))),
Handle<Object>(context->get(context_index), isolate),
::NONE,
SLOPPY),
diff --git a/src/scopes.cc b/src/scopes.cc
index 4c4729e..833198c 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -1266,7 +1266,7 @@
for (int i = params_.length() - 1; i >= 0; --i) {
Variable* var = params_[i];
ASSERT(var->scope() == this);
- if (uses_sloppy_arguments) {
+ if (uses_sloppy_arguments || has_forced_context_allocation()) {
// Force context allocation of the parameter.
var->ForceContextAllocation();
}
diff --git a/src/serialize.cc b/src/serialize.cc
index 4048886..2c0f510 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -276,10 +276,21 @@
ACCESSOR, \
Accessors::k##name, \
"Accessors::" #name);
-
ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
#undef ACCESSOR_DESCRIPTOR_DECLARATION
+#define ACCESSOR_INFO_DECLARATION(name) \
+ Add(FUNCTION_ADDR(&Accessors::name##Getter), \
+ ACCESSOR, \
+ Accessors::k##name##Getter, \
+ "Accessors::" #name "Getter"); \
+ Add(FUNCTION_ADDR(&Accessors::name##Setter), \
+ ACCESSOR, \
+ Accessors::k##name##Setter, \
+ "Accessors::" #name "Setter");
+ ACCESSOR_INFO_LIST(ACCESSOR_INFO_DECLARATION)
+#undef ACCESSOR_INFO_DECLARATION
+
StubCache* stub_cache = isolate->stub_cache();
// Stub cache tables
@@ -309,15 +320,6 @@
"StubCache::secondary_->map");
// Runtime entries
- Add(ExternalReference::perform_gc_function(isolate).address(),
- RUNTIME_ENTRY,
- 1,
- "Runtime::PerformGC");
- // Runtime entries
- Add(ExternalReference::out_of_memory_function(isolate).address(),
- RUNTIME_ENTRY,
- 2,
- "Runtime::OutOfMemory");
Add(ExternalReference::delete_handle_scope_extensions(isolate).address(),
RUNTIME_ENTRY,
4,
@@ -372,10 +374,6 @@
UNCLASSIFIED,
11,
"Heap::NewSpaceMask()");
- Add(ExternalReference::heap_always_allocate_scope_depth(isolate).address(),
- UNCLASSIFIED,
- 12,
- "Heap::always_allocate_scope_depth()");
Add(ExternalReference::new_space_allocation_limit_address(isolate).address(),
UNCLASSIFIED,
14,
@@ -575,7 +573,7 @@
ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate)
- : encodings_(Match),
+ : encodings_(HashMap::PointersMatch),
isolate_(isolate) {
ExternalReferenceTable* external_references =
ExternalReferenceTable::instance(isolate_);
@@ -638,10 +636,7 @@
DeleteArray(encodings_);
}
-
-bool Serializer::serialization_enabled_ = false;
-bool Serializer::too_late_to_enable_now_ = false;
-
+AtomicWord Serializer::serialization_state_ = SERIALIZER_STATE_UNINITIALIZED;
class CodeAddressMap: public CodeEventLogger {
public:
@@ -669,7 +664,7 @@
private:
class NameMap {
public:
- NameMap() : impl_(&PointerEquals) {}
+ NameMap() : impl_(HashMap::PointersMatch) {}
~NameMap() {
for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) {
@@ -709,10 +704,6 @@
}
private:
- static bool PointerEquals(void* lhs, void* rhs) {
- return lhs == rhs;
- }
-
static char* CopyName(const char* name, int name_size) {
char* result = NewArray<char>(name_size + 1);
for (int i = 0; i < name_size; ++i) {
@@ -758,22 +749,42 @@
CodeAddressMap* Serializer::code_address_map_ = NULL;
-void Serializer::Enable(Isolate* isolate) {
- if (!serialization_enabled_) {
- ASSERT(!too_late_to_enable_now_);
- }
- if (serialization_enabled_) return;
- serialization_enabled_ = true;
+void Serializer::RequestEnable(Isolate* isolate) {
isolate->InitializeLoggingAndCounters();
code_address_map_ = new CodeAddressMap(isolate);
}
-void Serializer::Disable() {
- if (!serialization_enabled_) return;
- serialization_enabled_ = false;
- delete code_address_map_;
- code_address_map_ = NULL;
+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);
}
@@ -865,7 +876,8 @@
Deserializer::~Deserializer() {
- ASSERT(source_->AtEOF());
+ // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed.
+ // ASSERT(source_->AtEOF());
if (external_reference_decoder_) {
delete external_reference_decoder_;
external_reference_decoder_ = NULL;
diff --git a/src/serialize.h b/src/serialize.h
index 2947144..9e1d3d5 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -124,8 +124,6 @@
int IndexOf(Address key) const;
- static bool Match(void* key1, void* key2) { return key1 == key2; }
-
void Put(Address key, int index);
Isolate* isolate_;
@@ -414,7 +412,7 @@
public:
SerializationAddressMapper()
: no_allocation_(),
- serialization_map_(new HashMap(&SerializationMatchFun)) { }
+ serialization_map_(new HashMap(HashMap::PointersMatch)) { }
~SerializationAddressMapper() {
delete serialization_map_;
@@ -438,10 +436,6 @@
}
private:
- static bool SerializationMatchFun(void* key1, void* key2) {
- return key1 == key2;
- }
-
static uint32_t Hash(HeapObject* obj) {
return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
}
@@ -476,13 +470,16 @@
}
Isolate* isolate() const { return isolate_; }
- static void Enable(Isolate* isolate);
- static void Disable();
+ static void RequestEnable(Isolate* isolate);
+ static void InitializeOncePerProcess();
+ static void TearDown();
- // Call this when you have made use of the fact that there is no serialization
- // going on.
- static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
- static bool enabled() { return serialization_enabled_; }
+ static bool enabled() {
+ 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,
@@ -580,9 +577,15 @@
int fullness_[LAST_SPACE + 1];
SnapshotByteSink* sink_;
ExternalReferenceEncoder* external_reference_encoder_;
- static bool serialization_enabled_;
- // Did we already make use of the fact that serialization was not enabled?
- static bool too_late_to_enable_now_;
+
+ 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();
diff --git a/src/spaces.cc b/src/spaces.cc
index dfa9cea..996afe4 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -27,6 +27,7 @@
#include "v8.h"
+#include "full-codegen.h"
#include "macro-assembler.h"
#include "mark-compact.h"
#include "msan.h"
@@ -1083,7 +1084,7 @@
// upgraded to handle small pages.
size = AreaSize();
} else {
- size = 480 * KB;
+ size = 480 * KB * FullCodeGenerator::kBootCodeSizeMultiplier / 100;
}
break;
default:
diff --git a/src/string-stream.cc b/src/string-stream.cc
index 93eb222..e9795ad 100644
--- a/src/string-stream.cc
+++ b/src/string-stream.cc
@@ -265,8 +265,14 @@
Handle<String> StringStream::ToString(Isolate* isolate) {
- return isolate->factory()->NewStringFromUtf8(
+ MaybeHandle<String> maybe_result = isolate->factory()->NewStringFromUtf8(
Vector<const char>(buffer_, length_));
+
+ // TODO(ishell): Temporarily returning null handle from here. I will proceed
+ // with maybehandlification in next CLs.
+ Handle<String> result;
+ if (!maybe_result.ToHandle(&result)) return Handle<String>();
+ return result;
}
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index e7bf069..4f60c80 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -478,7 +478,7 @@
// StubCompiler implementation.
-RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
+RUNTIME_FUNCTION(StoreCallbackProperty) {
JSObject* receiver = JSObject::cast(args[0]);
JSObject* holder = JSObject::cast(args[1]);
ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[2]);
@@ -499,7 +499,7 @@
PropertyCallbackArguments
custom_args(isolate, callback->data(), receiver, holder);
custom_args.Call(fun, v8::Utils::ToLocal(str), v8::Utils::ToLocal(value));
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return *value;
}
@@ -511,7 +511,7 @@
* Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
* provide any value for the given name.
*/
-RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
+RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly) {
ASSERT(args.length() == StubCache::kInterceptorArgsLength);
Handle<Name> name_handle =
args.at<Name>(StubCache::kInterceptorArgsNameIndex);
@@ -539,7 +539,7 @@
HandleScope scope(isolate);
v8::Handle<v8::Value> r =
callback_args.Call(getter, v8::Utils::ToLocal(name));
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
if (!r.IsEmpty()) {
Handle<Object> result = v8::Utils::OpenHandle(*r);
result->VerifyApiCallResultType();
@@ -551,7 +551,7 @@
}
-static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) {
+static Object* ThrowReferenceError(Isolate* isolate, Name* name) {
// If the load is non-contextual, just return the undefined result.
// Note that both keyed and non-keyed loads may end up here.
HandleScope scope(isolate);
@@ -623,7 +623,7 @@
* Loads a property with an interceptor performing post interceptor
* lookup if interceptor failed.
*/
-RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
+RUNTIME_FUNCTION(LoadPropertyWithInterceptorForLoad) {
PropertyAttributes attr = NONE;
HandleScope scope(isolate);
Handle<Object> result;
@@ -636,7 +636,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
+RUNTIME_FUNCTION(LoadPropertyWithInterceptorForCall) {
PropertyAttributes attr;
HandleScope scope(isolate);
Handle<Object> result;
@@ -649,7 +649,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
+RUNTIME_FUNCTION(StoreInterceptorProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
@@ -667,7 +667,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
+RUNTIME_FUNCTION(KeyedLoadPropertyWithInterceptor) {
HandleScope scope(isolate);
Handle<JSObject> receiver = args.at<JSObject>(0);
ASSERT(args.smi_at(1) >= 0);
@@ -901,7 +901,7 @@
// check that the global property cell is empty.
if (last_map->IsJSGlobalObjectMap()) {
Handle<JSGlobalObject> global = last.is_null()
- ? Handle<JSGlobalObject>::cast(type->AsConstant())
+ ? Handle<JSGlobalObject>::cast(type->AsConstant()->Value())
: Handle<JSGlobalObject>::cast(last);
GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
}
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 7a304fe..1e66613 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -288,15 +288,15 @@
// Support functions for IC stubs for callbacks.
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
+DECLARE_RUNTIME_FUNCTION(StoreCallbackProperty);
// Support functions for IC stubs for interceptors.
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
+DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly);
+DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorForLoad);
+DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorForCall);
+DECLARE_RUNTIME_FUNCTION(StoreInterceptorProperty);
+DECLARE_RUNTIME_FUNCTION(KeyedLoadPropertyWithInterceptor);
enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
@@ -309,7 +309,7 @@
explicit StubCompiler(Isolate* isolate,
ExtraICState extra_ic_state = kNoExtraICState)
: isolate_(isolate), extra_ic_state_(extra_ic_state),
- masm_(isolate, NULL, 256), failure_(NULL) { }
+ masm_(isolate, NULL, 256) { }
Handle<Code> CompileLoadInitialize(Code::Flags flags);
Handle<Code> CompileLoadPreMonomorphic(Code::Flags flags);
@@ -417,7 +417,6 @@
ExtraICState extra_state() { return extra_ic_state_; }
MacroAssembler* masm() { return &masm_; }
- void set_failure(Failure* failure) { failure_ = failure; }
static void LookupPostInterceptor(Handle<JSObject> holder,
Handle<Name> name,
diff --git a/src/types-inl.h b/src/types-inl.h
index ad1107b..ca4f120 100644
--- a/src/types-inl.h
+++ b/src/types-inl.h
@@ -13,6 +13,18 @@
namespace v8 {
namespace internal {
+// -------------------------------------------------------------------------- //
+// TypeImpl
+
+template<class Config>
+TypeImpl<Config>* TypeImpl<Config>::cast(typename Config::Base* object) {
+ TypeImpl* t = static_cast<TypeImpl*>(object);
+ ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() ||
+ t->IsUnion() || t->IsArray() || t->IsFunction());
+ return t;
+}
+
+
template<class Config>
bool TypeImpl<Config>::NowContains(i::Object* value) {
DisallowHeapAllocation no_allocation;
@@ -27,33 +39,44 @@
}
+// -------------------------------------------------------------------------- //
+// ZoneTypeConfig
+
// static
-Type* ZoneTypeConfig::handle(Type* type) {
+template<class T>
+T* ZoneTypeConfig::handle(T* type) {
return type;
}
// static
+template<class T>
+T* ZoneTypeConfig::cast(Type* type) {
+ return static_cast<T*>(type);
+}
+
+
+// static
bool ZoneTypeConfig::is_bitset(Type* type) {
return reinterpret_cast<intptr_t>(type) & 1;
}
// static
-bool ZoneTypeConfig::is_struct(Type* type) {
- return !is_bitset(type);
+bool ZoneTypeConfig::is_struct(Type* type, int tag) {
+ return !is_bitset(type) && struct_tag(as_struct(type)) == tag;
}
// static
bool ZoneTypeConfig::is_class(Type* type) {
- return is_struct(type) && struct_tag(as_struct(type)) == Type::kClassTag;
+ return is_struct(type, Type::StructuralType::kClassTag);
}
// static
bool ZoneTypeConfig::is_constant(Type* type) {
- return is_struct(type) && struct_tag(as_struct(type)) == Type::kConstantTag;
+ return is_struct(type, Type::StructuralType::kConstantTag);
}
@@ -66,7 +89,7 @@
// static
ZoneTypeConfig::Struct* ZoneTypeConfig::as_struct(Type* type) {
- ASSERT(is_struct(type));
+ ASSERT(!is_bitset(type));
return reinterpret_cast<Struct*>(type);
}
@@ -107,7 +130,7 @@
// static
ZoneTypeConfig::Type* ZoneTypeConfig::from_class(
i::Handle<i::Map> map, int lub, Zone* zone) {
- Struct* structured = struct_create(Type::kClassTag, 2, zone);
+ Struct* structured = struct_create(Type::StructuralType::kClassTag, 2, zone);
structured[2] = from_bitset(lub);
structured[3] = map.location();
return from_struct(structured);
@@ -117,7 +140,8 @@
// static
ZoneTypeConfig::Type* ZoneTypeConfig::from_constant(
i::Handle<i::Object> value, int lub, Zone* zone) {
- Struct* structured = struct_create(Type::kConstantTag, 2, zone);
+ Struct* structured =
+ struct_create(Type::StructuralType::kConstantTag, 2, zone);
structured[2] = from_bitset(lub);
structured[3] = value.location();
return from_struct(structured);
@@ -174,15 +198,25 @@
return as_bitset(struct_get(as_struct(type), 0));
}
+
// -------------------------------------------------------------------------- //
+// HeapTypeConfig
// static
-i::Handle<HeapTypeConfig::Type> HeapTypeConfig::handle(Type* type) {
+template<class T>
+i::Handle<T> HeapTypeConfig::handle(T* type) {
return i::handle(type, i::HeapObject::cast(type)->GetIsolate());
}
// static
+template<class T>
+i::Handle<T> HeapTypeConfig::cast(i::Handle<Type> type) {
+ return i::Handle<T>::cast(type);
+}
+
+
+// static
bool HeapTypeConfig::is_bitset(Type* type) {
return type->IsSmi();
}
@@ -201,14 +235,14 @@
// static
-bool HeapTypeConfig::is_struct(Type* type) {
- return type->IsFixedArray();
+bool HeapTypeConfig::is_struct(Type* type, int tag) {
+ return type->IsFixedArray() && struct_tag(as_struct(type)) == tag;
}
// static
int HeapTypeConfig::as_bitset(Type* type) {
- return Smi::cast(type)->value();
+ return i::Smi::cast(type)->value();
}
diff --git a/src/types.cc b/src/types.cc
index 4ddc14b..705b64e 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -12,13 +12,14 @@
template<class Config>
int TypeImpl<Config>::NumClasses() {
+ DisallowHeapAllocation no_allocation;
if (this->IsClass()) {
return 1;
} else if (this->IsUnion()) {
- StructHandle unioned = this->AsUnion();
+ UnionHandle unioned = handle(this->AsUnion());
int result = 0;
- for (int i = 0; i < Config::struct_length(unioned); ++i) {
- if (Config::struct_get(unioned, i)->IsClass()) ++result;
+ for (int i = 0; i < unioned->Length(); ++i) {
+ if (unioned->Get(i)->IsClass()) ++result;
}
return result;
} else {
@@ -29,13 +30,14 @@
template<class Config>
int TypeImpl<Config>::NumConstants() {
+ DisallowHeapAllocation no_allocation;
if (this->IsConstant()) {
return 1;
} else if (this->IsUnion()) {
- StructHandle unioned = this->AsUnion();
+ UnionHandle unioned = handle(this->AsUnion());
int result = 0;
- for (int i = 0; i < Config::struct_length(unioned); ++i) {
- if (Config::struct_get(unioned, i)->IsConstant()) ++result;
+ for (int i = 0; i < unioned->Length(); ++i) {
+ if (unioned->Get(i)->IsConstant()) ++result;
}
return result;
} else {
@@ -48,8 +50,7 @@
typename TypeImpl<Config>::TypeHandle
TypeImpl<Config>::Iterator<T>::get_type() {
ASSERT(!Done());
- return type_->IsUnion()
- ? Config::struct_get(type_->AsUnion(), index_) : type_;
+ return type_->IsUnion() ? type_->AsUnion()->Get(index_) : type_;
}
@@ -67,7 +68,7 @@
return type->IsClass();
}
static i::Handle<i::Map> current(typename TypeImpl<Config>::TypeHandle type) {
- return type->AsClass();
+ return type->AsClass()->Map();
}
};
@@ -78,7 +79,7 @@
}
static i::Handle<i::Object> current(
typename TypeImpl<Config>::TypeHandle type) {
- return type->AsConstant();
+ return type->AsConstant()->Value();
}
};
@@ -95,11 +96,12 @@
template<class Config> template<class T>
void TypeImpl<Config>::Iterator<T>::Advance() {
+ DisallowHeapAllocation no_allocation;
++index_;
if (type_->IsUnion()) {
- StructHandle unioned = type_->AsUnion();
- for (; index_ < Config::struct_length(unioned); ++index_) {
- if (matches(Config::struct_get(unioned, index_))) return;
+ UnionHandle unioned = handle(type_->AsUnion());
+ for (; index_ < unioned->Length(); ++index_) {
+ if (matches(unioned->Get(index_))) return;
}
} else if (index_ == 0 && matches(type_)) {
return;
@@ -108,30 +110,54 @@
}
+// Get the largest bitset subsumed by this type.
+template<class Config>
+int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) {
+ DisallowHeapAllocation no_allocation;
+ if (type->IsBitset()) {
+ return type->AsBitset();
+ } else if (type->IsUnion()) {
+ // All but the first are non-bitsets and thus would yield kNone anyway.
+ return type->AsUnion()->Get(0)->BitsetGlb();
+ } else {
+ return kNone;
+ }
+}
+
+
// Get the smallest bitset subsuming this type.
template<class Config>
-int TypeImpl<Config>::LubBitset() {
- if (this->IsBitset()) {
- return this->AsBitset();
- } else if (this->IsUnion()) {
- StructHandle unioned = this->AsUnion();
+int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
+ DisallowHeapAllocation no_allocation;
+ if (type->IsBitset()) {
+ return type->AsBitset();
+ } else if (type->IsUnion()) {
+ UnionHandle unioned = handle(type->AsUnion());
int bitset = kNone;
- for (int i = 0; i < Config::struct_length(unioned); ++i) {
- bitset |= Config::struct_get(unioned, i)->LubBitset();
+ for (int i = 0; i < unioned->Length(); ++i) {
+ bitset |= unioned->Get(i)->BitsetLub();
}
return bitset;
- } else if (this->IsClass()) {
- int bitset = Config::lub_bitset(this);
- return bitset ? bitset : LubBitset(*this->AsClass());
+ } else if (type->IsClass()) {
+ int bitset = Config::lub_bitset(type);
+ return bitset ? bitset : Lub(*type->AsClass()->Map());
+ } else if (type->IsConstant()) {
+ int bitset = Config::lub_bitset(type);
+ return bitset ? bitset : Lub(*type->AsConstant()->Value());
+ } else if (type->IsArray()) {
+ return kArray;
+ } else if (type->IsFunction()) {
+ return kFunction;
} else {
- int bitset = Config::lub_bitset(this);
- return bitset ? bitset : LubBitset(*this->AsConstant());
+ UNREACHABLE();
+ return kNone;
}
}
template<class Config>
-int TypeImpl<Config>::LubBitset(i::Object* value) {
+int TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
+ DisallowHeapAllocation no_allocation;
if (value->IsSmi()) return kSignedSmall & kTaggedInt;
i::Map* map = i::HeapObject::cast(value)->map();
if (map->instance_type() == HEAP_NUMBER_TYPE) {
@@ -141,12 +167,13 @@
value->ToInt32(&i) ? (Smi::IsValid(i) ? kSignedSmall : kOtherSigned32) :
value->ToUint32(&u) ? kUnsigned32 : kFloat);
}
- return LubBitset(map);
+ return Lub(map);
}
template<class Config>
-int TypeImpl<Config>::LubBitset(i::Map* map) {
+int TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
+ DisallowHeapAllocation no_allocation;
switch (map->instance_type()) {
case STRING_TYPE:
case ASCII_STRING_TYPE:
@@ -199,6 +226,8 @@
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
+ case JS_SET_ITERATOR_TYPE:
+ case JS_MAP_ITERATOR_TYPE:
case JS_WEAK_MAP_TYPE:
case JS_WEAK_SET_TYPE:
if (map->is_undetectable()) return kUndetectable;
@@ -235,20 +264,6 @@
}
-// Get the largest bitset subsumed by this type.
-template<class Config>
-int TypeImpl<Config>::GlbBitset() {
- if (this->IsBitset()) {
- return this->AsBitset();
- } else if (this->IsUnion()) {
- // All but the first are non-bitsets and thus would yield kNone anyway.
- return Config::struct_get(this->AsUnion(), 0)->GlbBitset();
- } else {
- return kNone;
- }
-}
-
-
// Most precise _current_ type of a value (usually its class).
template<class Config>
typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NowOf(
@@ -264,25 +279,48 @@
// Check this <= that.
template<class Config>
bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
+ DisallowHeapAllocation no_allocation;
+
// Fast path for bitsets.
if (this->IsNone()) return true;
if (that->IsBitset()) {
- return (this->LubBitset() | that->AsBitset()) == that->AsBitset();
+ return (BitsetType::Lub(this) | that->AsBitset()) == that->AsBitset();
}
if (that->IsClass()) {
- return this->IsClass() && *this->AsClass() == *that->AsClass();
+ return this->IsClass()
+ && *this->AsClass()->Map() == *that->AsClass()->Map();
}
if (that->IsConstant()) {
- return this->IsConstant() && *this->AsConstant() == *that->AsConstant();
+ return this->IsConstant()
+ && *this->AsConstant()->Value() == *that->AsConstant()->Value();
+ }
+ if (that->IsArray()) {
+ return this->IsArray()
+ && this->AsArray()->Element()->Equals(that->AsArray()->Element());
+ }
+ if (that->IsFunction()) {
+ // We currently do not allow for any variance here, in order to keep
+ // Union and Intersect operations simple.
+ if (!this->IsFunction()) return false;
+ FunctionType* this_fun = this->AsFunction();
+ FunctionType* that_fun = that->AsFunction();
+ if (this_fun->Arity() != that_fun->Arity() ||
+ !this_fun->Result()->Equals(that_fun->Result()) ||
+ !that_fun->Receiver()->Equals(this_fun->Receiver())) {
+ return false;
+ }
+ for (int i = 0; i < this_fun->Arity(); ++i) {
+ if (!that_fun->Parameter(i)->Equals(this_fun->Parameter(i))) return false;
+ }
+ return true;
}
// (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T)
if (this->IsUnion()) {
- StructHandle unioned = this->AsUnion();
- for (int i = 0; i < Config::struct_length(unioned); ++i) {
- TypeHandle this_i = Config::struct_get(unioned, i);
- if (!this_i->Is(that)) return false;
+ UnionHandle unioned = handle(this->AsUnion());
+ for (int i = 0; i < unioned->Length(); ++i) {
+ if (!unioned->Get(i)->Is(that)) return false;
}
return true;
}
@@ -291,10 +329,9 @@
// (iff T is not a union)
ASSERT(!this->IsUnion());
if (that->IsUnion()) {
- StructHandle unioned = that->AsUnion();
- for (int i = 0; i < Config::struct_length(unioned); ++i) {
- TypeHandle that_i = Config::struct_get(unioned, i);
- if (this->Is(that_i)) return true;
+ UnionHandle unioned = handle(that->AsUnion());
+ for (int i = 0; i < unioned->Length(); ++i) {
+ if (this->Is(unioned->Get(i))) return true;
if (this->IsBitset()) break; // Fast fail, only first field is a bitset.
}
return false;
@@ -306,12 +343,13 @@
template<class Config>
bool TypeImpl<Config>::NowIs(TypeImpl* that) {
+ DisallowHeapAllocation no_allocation;
+
// TODO(rossberg): this is incorrect for
// Union(Constant(V), T)->NowIs(Class(M))
// but fuzzing does not cover that!
- DisallowHeapAllocation no_allocation;
if (this->IsConstant()) {
- i::Object* object = *this->AsConstant();
+ i::Object* object = *this->AsConstant()->Value();
if (object->IsHeapObject()) {
i::Map* map = i::HeapObject::cast(object)->map();
for (Iterator<i::Map> it = that->Classes(); !it.Done(); it.Advance()) {
@@ -323,42 +361,62 @@
}
+// Check if this contains only (currently) stable classes.
+template<class Config>
+bool TypeImpl<Config>::NowStable() {
+ DisallowHeapAllocation no_allocation;
+ for (Iterator<i::Map> it = this->Classes(); !it.Done(); it.Advance()) {
+ if (!it.Current()->is_stable()) return false;
+ }
+ return true;
+}
+
+
// Check this overlaps that.
template<class Config>
bool TypeImpl<Config>::Maybe(TypeImpl* that) {
+ DisallowHeapAllocation no_allocation;
+
// (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
if (this->IsUnion()) {
- StructHandle unioned = this->AsUnion();
- for (int i = 0; i < Config::struct_length(unioned); ++i) {
- TypeHandle this_i = Config::struct_get(unioned, i);
- if (this_i->Maybe(that)) return true;
+ UnionHandle unioned = handle(this->AsUnion());
+ for (int i = 0; i < unioned->Length(); ++i) {
+ if (unioned->Get(i)->Maybe(that)) return true;
}
return false;
}
// T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn)
if (that->IsUnion()) {
- StructHandle unioned = that->AsUnion();
- for (int i = 0; i < Config::struct_length(unioned); ++i) {
- TypeHandle that_i = Config::struct_get(unioned, i);
- if (this->Maybe(that_i)) return true;
+ UnionHandle unioned = handle(that->AsUnion());
+ for (int i = 0; i < unioned->Length(); ++i) {
+ if (this->Maybe(unioned->Get(i))) return true;
}
return false;
}
ASSERT(!this->IsUnion() && !that->IsUnion());
if (this->IsBitset()) {
- return IsInhabited(this->AsBitset() & that->LubBitset());
+ return BitsetType::IsInhabited(this->AsBitset() & that->BitsetLub());
}
if (that->IsBitset()) {
- return IsInhabited(this->LubBitset() & that->AsBitset());
+ return BitsetType::IsInhabited(this->BitsetLub() & that->AsBitset());
}
-
if (this->IsClass()) {
- return that->IsClass() && *this->AsClass() == *that->AsClass();
+ return that->IsClass()
+ && *this->AsClass()->Map() == *that->AsClass()->Map();
}
if (this->IsConstant()) {
- return that->IsConstant() && *this->AsConstant() == *that->AsConstant();
+ return that->IsConstant()
+ && *this->AsConstant()->Value() == *that->AsConstant()->Value();
+ }
+ if (this->IsArray()) {
+ // There is no variance!
+ return this->Equals(that);
+ }
+ if (this->IsFunction()) {
+ // There is no variance!
+ return this->Equals(that);
}
return false;
@@ -367,19 +425,20 @@
template<class Config>
bool TypeImpl<Config>::Contains(i::Object* value) {
+ DisallowHeapAllocation no_allocation;
+
for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) {
if (*it.Current() == value) return true;
}
- return Config::from_bitset(LubBitset(value))->Is(this);
+ return BitsetType::New(BitsetType::Lub(value))->Is(this);
}
template<class Config>
-bool TypeImpl<Config>::InUnion(StructHandle unioned, int current_size) {
+bool TypeImpl<Config>::InUnion(UnionHandle unioned, int current_size) {
ASSERT(!this->IsUnion());
for (int i = 0; i < current_size; ++i) {
- TypeHandle type = Config::struct_get(unioned, i);
- if (this->Is(type)) return true;
+ if (this->Is(unioned->Get(i))) return true;
}
return false;
}
@@ -389,22 +448,24 @@
// starting at index. Returns updated index.
template<class Config>
int TypeImpl<Config>::ExtendUnion(
- StructHandle result, TypeHandle type, int current_size) {
+ UnionHandle result, TypeHandle type, int current_size) {
int old_size = current_size;
- if (type->IsClass() || type->IsConstant()) {
- if (!type->InUnion(result, old_size)) {
- Config::struct_set(result, current_size++, type);
- }
- } else if (type->IsUnion()) {
- StructHandle unioned = type->AsUnion();
- for (int i = 0; i < Config::struct_length(unioned); ++i) {
- TypeHandle type = Config::struct_get(unioned, i);
- ASSERT(i == 0 ||
- !(type->IsBitset() || type->Is(Config::struct_get(unioned, 0))));
+ if (type->IsUnion()) {
+ UnionHandle unioned = handle(type->AsUnion());
+ for (int i = 0; i < unioned->Length(); ++i) {
+ TypeHandle type = unioned->Get(i);
+ ASSERT(i == 0 || !(type->IsBitset() || type->Is(unioned->Get(0))));
if (!type->IsBitset() && !type->InUnion(result, old_size)) {
- Config::struct_set(result, current_size++, type);
+ result->Set(current_size++, type);
}
}
+ } else if (!type->IsBitset()) {
+ // For all structural types, subtyping implies equivalence.
+ ASSERT(type->IsClass() || type->IsConstant() ||
+ type->IsArray() || type->IsFunction());
+ if (!type->InUnion(result, old_size)) {
+ result->Set(current_size++, type);
+ }
}
return current_size;
}
@@ -416,7 +477,7 @@
TypeHandle type1, TypeHandle type2, Region* region) {
// Fast case: bit sets.
if (type1->IsBitset() && type2->IsBitset()) {
- return Config::from_bitset(type1->AsBitset() | type2->AsBitset(), region);
+ return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region);
}
// Fast case: top or bottom types.
@@ -432,28 +493,28 @@
// Slow case: may need to produce a Unioned object.
int size = 0;
if (!type1->IsBitset()) {
- size += (type1->IsUnion() ? Config::struct_length(type1->AsUnion()) : 1);
+ size += (type1->IsUnion() ? type1->AsUnion()->Length() : 1);
}
if (!type2->IsBitset()) {
- size += (type2->IsUnion() ? Config::struct_length(type2->AsUnion()) : 1);
+ size += (type2->IsUnion() ? type2->AsUnion()->Length() : 1);
}
- int bitset = type1->GlbBitset() | type2->GlbBitset();
- if (bitset != kNone) ++size;
+ int bitset = type1->BitsetGlb() | type2->BitsetGlb();
+ if (bitset != BitsetType::kNone) ++size;
ASSERT(size >= 1);
- StructHandle unioned = Config::struct_create(kUnionTag, size, region);
+ UnionHandle unioned = UnionType::New(size, region);
size = 0;
- if (bitset != kNone) {
- Config::struct_set(unioned, size++, Config::from_bitset(bitset, region));
+ if (bitset != BitsetType::kNone) {
+ unioned->Set(size++, BitsetType::New(bitset, region));
}
size = ExtendUnion(unioned, type1, size);
size = ExtendUnion(unioned, type2, size);
if (size == 1) {
- return Config::struct_get(unioned, 0);
+ return unioned->Get(0);
} else {
- Config::struct_shrink(unioned, size);
- return Config::from_struct(unioned);
+ unioned->Shrink(size);
+ return unioned;
}
}
@@ -462,36 +523,37 @@
// starting at index. Returns updated index.
template<class Config>
int TypeImpl<Config>::ExtendIntersection(
- StructHandle result, TypeHandle type, TypeHandle other, int current_size) {
+ UnionHandle result, TypeHandle type, TypeHandle other, int current_size) {
int old_size = current_size;
- if (type->IsClass() || type->IsConstant()) {
- if (type->Is(other) && !type->InUnion(result, old_size)) {
- Config::struct_set(result, current_size++, type);
- }
- } else if (type->IsUnion()) {
- StructHandle unioned = type->AsUnion();
- for (int i = 0; i < Config::struct_length(unioned); ++i) {
- TypeHandle type = Config::struct_get(unioned, i);
- ASSERT(i == 0 ||
- !(type->IsBitset() || type->Is(Config::struct_get(unioned, 0))));
+ if (type->IsUnion()) {
+ UnionHandle unioned = handle(type->AsUnion());
+ for (int i = 0; i < unioned->Length(); ++i) {
+ TypeHandle type = unioned->Get(i);
+ ASSERT(i == 0 || !(type->IsBitset() || type->Is(unioned->Get(0))));
if (!type->IsBitset() && type->Is(other) &&
!type->InUnion(result, old_size)) {
- Config::struct_set(result, current_size++, type);
+ result->Set(current_size++, type);
}
}
+ } else if (!type->IsBitset()) {
+ // For all structural types, subtyping implies equivalence.
+ ASSERT(type->IsClass() || type->IsConstant() ||
+ type->IsArray() || type->IsFunction());
+ if (type->Is(other) && !type->InUnion(result, old_size)) {
+ result->Set(current_size++, type);
+ }
}
return current_size;
}
// Intersection is O(1) on simple bit unions, but O(n*m) on structured unions.
-// TODO(rossberg): Should we use object sets somehow? Is it worth it?
template<class Config>
typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
TypeHandle type1, TypeHandle type2, Region* region) {
// Fast case: bit sets.
if (type1->IsBitset() && type2->IsBitset()) {
- return Config::from_bitset(type1->AsBitset() & type2->AsBitset(), region);
+ return BitsetType::New(type1->AsBitset() & type2->AsBitset(), region);
}
// Fast case: top or bottom types.
@@ -507,19 +569,19 @@
// Slow case: may need to produce a Unioned object.
int size = 0;
if (!type1->IsBitset()) {
- size += (type1->IsUnion() ? Config::struct_length(type1->AsUnion()) : 1);
+ size += (type1->IsUnion() ? type1->AsUnion()->Length() : 1);
}
if (!type2->IsBitset()) {
- size += (type2->IsUnion() ? Config::struct_length(type2->AsUnion()) : 1);
+ size += (type2->IsUnion() ? type2->AsUnion()->Length() : 1);
}
- int bitset = type1->GlbBitset() & type2->GlbBitset();
- if (bitset != kNone) ++size;
+ int bitset = type1->BitsetGlb() & type2->BitsetGlb();
+ if (bitset != BitsetType::kNone) ++size;
ASSERT(size >= 1);
- StructHandle unioned = Config::struct_create(kUnionTag, size, region);
+ UnionHandle unioned = UnionType::New(size, region);
size = 0;
- if (bitset != kNone) {
- Config::struct_set(unioned, size++, Config::from_bitset(bitset, region));
+ if (bitset != BitsetType::kNone) {
+ unioned->Set(size++, BitsetType::New(bitset, region));
}
size = ExtendIntersection(unioned, type1, type2, size);
size = ExtendIntersection(unioned, type2, type1, size);
@@ -527,10 +589,10 @@
if (size == 0) {
return None(region);
} else if (size == 1) {
- return Config::struct_get(unioned, 0);
+ return unioned->Get(0);
} else {
- Config::struct_shrink(unioned, size);
- return Config::from_struct(unioned);
+ unioned->Shrink(size);
+ return unioned;
}
}
@@ -540,27 +602,41 @@
typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert(
typename OtherType::TypeHandle type, Region* region) {
if (type->IsBitset()) {
- return Config::from_bitset(type->AsBitset(), region);
+ return BitsetType::New(type->AsBitset(), region);
} else if (type->IsClass()) {
- return Config::from_class(type->AsClass(), type->LubBitset(), region);
+ return ClassType::New(type->AsClass()->Map(), region);
} else if (type->IsConstant()) {
- return Config::from_constant(type->AsConstant(), type->LubBitset(), region);
- } else {
- ASSERT(type->IsUnion());
- typename OtherType::StructHandle unioned = type->AsUnion();
- int length = OtherType::StructLength(unioned);
- StructHandle new_unioned = Config::struct_create(kUnionTag, length, region);
+ return ConstantType::New(type->AsConstant()->Value(), region);
+ } else if (type->IsUnion()) {
+ int length = type->AsUnion()->Length();
+ UnionHandle unioned = UnionType::New(length, region);
for (int i = 0; i < length; ++i) {
- Config::struct_set(new_unioned, i,
- Convert<OtherType>(OtherType::StructGet(unioned, i), region));
+ unioned->Set(i, Convert<OtherType>(type->AsUnion()->Get(i), region));
}
- return Config::from_struct(new_unioned);
+ return unioned;
+ } else if (type->IsArray()) {
+ return ArrayType::New(
+ Convert<OtherType>(type->AsArray()->Element(), region), region);
+ } else if (type->IsFunction()) {
+ FunctionHandle function = FunctionType::New(
+ Convert<OtherType>(type->AsFunction()->Result(), region),
+ Convert<OtherType>(type->AsFunction()->Receiver(), region),
+ type->AsFunction()->Arity(), region);
+ for (int i = 0; i < function->Arity(); ++i) {
+ function->InitParameter(i,
+ Convert<OtherType>(type->AsFunction()->Parameter(i), region));
+ }
+ return function;
+ } else {
+ UNREACHABLE();
+ return None(region);
}
}
// TODO(rossberg): this does not belong here.
Representation Representation::FromType(Type* type) {
+ DisallowHeapAllocation no_allocation;
if (type->Is(Type::None())) return Representation::None();
if (type->Is(Type::SignedSmall())) return Representation::Smi();
if (type->Is(Type::Signed32())) return Representation::Integer32();
@@ -578,7 +654,7 @@
template<class Config>
-const char* TypeImpl<Config>::bitset_name(int bitset) {
+const char* TypeImpl<Config>::BitsetType::Name(int bitset) {
switch (bitset) {
case kAny & kRepresentation: return "Any";
#define PRINT_COMPOSED_TYPE(type, value) \
@@ -598,8 +674,9 @@
template<class Config>
-void TypeImpl<Config>::BitsetTypePrint(FILE* out, int bitset) {
- const char* name = bitset_name(bitset);
+void TypeImpl<Config>::BitsetType::BitsetTypePrint(FILE* out, int bitset) {
+ DisallowHeapAllocation no_allocation;
+ const char* name = Name(bitset);
if (name != NULL) {
PrintF(out, "%s", name);
} else {
@@ -620,7 +697,7 @@
if ((bitset & subset) == subset) {
if (!is_first) PrintF(out, " | ");
is_first = false;
- PrintF(out, "%s", bitset_name(subset));
+ PrintF(out, "%s", Name(subset));
bitset -= subset;
}
}
@@ -632,38 +709,58 @@
template<class Config>
void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) {
+ DisallowHeapAllocation no_allocation;
if (this->IsBitset()) {
int bitset = this->AsBitset();
switch (dim) {
case BOTH_DIMS:
- BitsetTypePrint(out, bitset & kSemantic);
+ BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic);
PrintF(out, "/");
- BitsetTypePrint(out, bitset & kRepresentation);
+ BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation);
break;
case SEMANTIC_DIM:
- BitsetTypePrint(out, bitset & kSemantic);
+ BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic);
break;
case REPRESENTATION_DIM:
- BitsetTypePrint(out, bitset & kRepresentation);
+ BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation);
break;
}
} else if (this->IsConstant()) {
- PrintF(out, "Constant(%p : ", static_cast<void*>(*this->AsConstant()));
- Config::from_bitset(this->LubBitset())->TypePrint(out, dim);
+ PrintF(out, "Constant(%p : ",
+ static_cast<void*>(*this->AsConstant()->Value()));
+ BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim);
PrintF(out, ")");
} else if (this->IsClass()) {
- PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()));
- Config::from_bitset(this->LubBitset())->TypePrint(out, dim);
+ PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()->Map()));
+ BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim);
PrintF(out, ")");
} else if (this->IsUnion()) {
PrintF(out, "(");
- StructHandle unioned = this->AsUnion();
- for (int i = 0; i < Config::struct_length(unioned); ++i) {
- TypeHandle type_i = Config::struct_get(unioned, i);
+ UnionHandle unioned = handle(this->AsUnion());
+ for (int i = 0; i < unioned->Length(); ++i) {
+ TypeHandle type_i = unioned->Get(i);
if (i > 0) PrintF(out, " | ");
type_i->TypePrint(out, dim);
}
PrintF(out, ")");
+ } else if (this->IsArray()) {
+ PrintF(out, "[");
+ AsArray()->Element()->TypePrint(out, dim);
+ PrintF(out, "]");
+ } else if (this->IsFunction()) {
+ if (!this->AsFunction()->Receiver()->IsAny()) {
+ this->AsFunction()->Receiver()->TypePrint(out, dim);
+ PrintF(out, ".");
+ }
+ PrintF(out, "(");
+ for (int i = 0; i < this->AsFunction()->Arity(); ++i) {
+ if (i > 0) PrintF(out, ", ");
+ this->AsFunction()->Parameter(i)->TypePrint(out, dim);
+ }
+ PrintF(out, ")->");
+ this->AsFunction()->Result()->TypePrint(out, dim);
+ } else {
+ UNREACHABLE();
}
}
diff --git a/src/types.h b/src/types.h
index 3a3bc3b..5ca3a81 100644
--- a/src/types.h
+++ b/src/types.h
@@ -43,7 +43,11 @@
//
// Class(map) < T iff instance_type(map) < T
// Constant(x) < T iff instance_type(map(x)) < T
+// Array(T) < Array
+// Function(R, S, T0, T1, ...) < Function
//
+// Both structural Array and Function types are invariant in all parameters.
+// Relaxing this would make Union and Intersect operations more involved.
// Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can
// change! (Its instance type cannot, however.)
// TODO(rossberg): the latter is not currently true for proxies, because of fix,
@@ -92,7 +96,7 @@
// lattice. That is intentional. It should always be possible to refine the
// lattice (e.g., splitting up number types further) without invalidating any
// existing assumptions or tests.
-// Consequently, do not use pointer equality for type tests, always use Is!
+// Consequently, do not normally use Equals for type tests, always use Is!
//
// The NowIs operator implements state-sensitive subtying, as described above.
// Any compilation decision based on such temporary properties requires runtime
@@ -189,15 +193,17 @@
// struct Config {
+// typedef TypeImpl<Config> Type;
// typedef Base;
// typedef Struct;
// typedef Region;
// template<class> struct Handle { typedef type; } // No template typedefs...
-// static Handle<Type>::type handle(Type* type); // !is_bitset(type)
+// template<class T> static Handle<T>::type handle(T* t); // !is_bitset(t)
+// template<class T> static Handle<T>::type cast(Handle<Type>::type);
// static bool is_bitset(Type*);
// static bool is_class(Type*);
// static bool is_constant(Type*);
-// static bool is_struct(Type*);
+// static bool is_struct(Type*, int tag);
// static int as_bitset(Type*);
// static i::Handle<i::Map> as_class(Type*);
// static i::Handle<i::Object> as_constant(Type*);
@@ -206,7 +212,7 @@
// static Handle<Type>::type from_bitset(int bitset, Region*);
// static Handle<Type>::type from_class(i::Handle<Map>, int lub, Region*);
// static Handle<Type>::type from_constant(i::Handle<Object>, int, Region*);
-// static Handle<Type>::type from_struct(Handle<Struct>::type);
+// static Handle<Type>::type from_struct(Handle<Struct>::type, int tag);
// static Handle<Struct>::type struct_create(int tag, int length, Region*);
// static void struct_shrink(Handle<Struct>::type, int length);
// static int struct_tag(Handle<Struct>::type);
@@ -218,36 +224,73 @@
template<class Config>
class TypeImpl : public Config::Base {
public:
+ class BitsetType; // Internal
+ class StructuralType; // Internal
+ class UnionType; // Internal
+
+ class ClassType;
+ class ConstantType;
+ class ArrayType;
+ class FunctionType;
+
typedef typename Config::template Handle<TypeImpl>::type TypeHandle;
+ typedef typename Config::template Handle<ClassType>::type ClassHandle;
+ typedef typename Config::template Handle<ConstantType>::type ConstantHandle;
+ typedef typename Config::template Handle<ArrayType>::type ArrayHandle;
+ typedef typename Config::template Handle<FunctionType>::type FunctionHandle;
+ typedef typename Config::template Handle<UnionType>::type UnionHandle;
typedef typename Config::Region Region;
- #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
- static TypeImpl* type() { return Config::from_bitset(k##type); } \
- static TypeHandle type(Region* region) { \
- return Config::from_bitset(k##type, region); \
+ #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
+ static TypeImpl* type() { return BitsetType::New(BitsetType::k##type); } \
+ static TypeHandle type(Region* region) { \
+ return BitsetType::New(BitsetType::k##type, region); \
}
BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
#undef DEFINE_TYPE_CONSTRUCTOR
static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
- return Config::from_class(map, LubBitset(*map), region);
+ return ClassType::New(map, region);
}
static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
- return Config::from_constant(value, LubBitset(*value), region);
+ return ConstantType::New(value, region);
+ }
+ static TypeHandle Array(TypeHandle element, Region* region) {
+ return ArrayType::New(element, region);
+ }
+ static FunctionHandle Function(
+ TypeHandle result, TypeHandle receiver, int arity, Region* region) {
+ return FunctionType::New(result, receiver, arity, region);
+ }
+ static TypeHandle Function(TypeHandle result, Region* region) {
+ return Function(result, Any(region), 0, region);
+ }
+ static TypeHandle Function(
+ TypeHandle result, TypeHandle param0, Region* region) {
+ FunctionHandle function = Function(result, Any(region), 1, region);
+ function->InitParameter(0, param0);
+ return function;
+ }
+ static TypeHandle Function(
+ TypeHandle result, TypeHandle param0, TypeHandle param1, Region* region) {
+ FunctionHandle function = Function(result, Any(region), 2, region);
+ function->InitParameter(0, param0);
+ function->InitParameter(1, param1);
+ return function;
}
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
static TypeHandle Of(i::Object* value, Region* region) {
- return Config::from_bitset(LubBitset(value), region);
+ return Config::from_bitset(BitsetType::Lub(value), region);
}
static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
return Of(*value, region);
}
bool IsInhabited() {
- return !this->IsBitset() || IsInhabited(this->AsBitset());
+ return !this->IsBitset() || BitsetType::IsInhabited(this->AsBitset());
}
bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
@@ -258,6 +301,10 @@
template<class TypeHandle>
bool Maybe(TypeHandle that) { return this->Maybe(*that); }
+ bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); }
+ template<class TypeHandle>
+ bool Equals(TypeHandle that) { return this->Equals(*that); }
+
// Equivalent to Constant(value)->Is(this), but avoiding allocation.
bool Contains(i::Object* val);
bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
@@ -274,36 +321,24 @@
inline bool NowContains(i::Object* val);
bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); }
+ bool NowStable();
+
bool IsClass() { return Config::is_class(this); }
bool IsConstant() { return Config::is_constant(this); }
- i::Handle<i::Map> AsClass() { return Config::as_class(this); }
- i::Handle<i::Object> AsConstant() { return Config::as_constant(this); }
+ bool IsArray() { return Config::is_struct(this, StructuralType::kArrayTag); }
+ bool IsFunction() {
+ return Config::is_struct(this, StructuralType::kFunctionTag);
+ }
+
+ ClassType* AsClass() { return ClassType::cast(this); }
+ ConstantType* AsConstant() { return ConstantType::cast(this); }
+ ArrayType* AsArray() { return ArrayType::cast(this); }
+ FunctionType* AsFunction() { return FunctionType::cast(this); }
int NumClasses();
int NumConstants();
- template<class T>
- class Iterator {
- public:
- bool Done() const { return index_ < 0; }
- i::Handle<T> Current();
- void Advance();
-
- private:
- template<class> friend class TypeImpl;
-
- Iterator() : index_(-1) {}
- explicit Iterator(TypeHandle type) : type_(type), index_(-1) {
- Advance();
- }
-
- inline bool matches(TypeHandle type);
- inline TypeHandle get_type();
-
- TypeHandle type_;
- int index_;
- };
-
+ template<class T> class Iterator;
Iterator<i::Map> Classes() {
if (this->IsBitset()) return Iterator<i::Map>();
return Iterator<i::Map>(Config::handle(this));
@@ -313,11 +348,7 @@
return Iterator<i::Object>(Config::handle(this));
}
- static TypeImpl* cast(typename Config::Base* object) {
- TypeImpl* t = static_cast<TypeImpl*>(object);
- ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion());
- return t;
- }
+ static inline TypeImpl* cast(typename Config::Base* object);
template<class OtherTypeImpl>
static TypeHandle Convert(
@@ -327,25 +358,43 @@
void TypePrint(PrintDimension = BOTH_DIMS);
void TypePrint(FILE* out, PrintDimension = BOTH_DIMS);
- private:
+ protected:
template<class> friend class Iterator;
template<class> friend class TypeImpl;
- friend struct ZoneTypeConfig;
- friend struct HeapTypeConfig;
- enum Tag {
- kClassTag,
- kConstantTag,
- kUnionTag
- };
+ template<class T>
+ static typename Config::template Handle<T>::type handle(T* type) {
+ return Config::handle(type);
+ }
- // A structured type contains a tag an a variable number of type fields.
- // A union is a structured type with the following invariants:
- // - its length is at least 2
- // - at most one field is a bitset, and it must go into index 0
- // - no field is a union
- typedef typename Config::Struct Struct;
- typedef typename Config::template Handle<Struct>::type StructHandle;
+ bool IsNone() { return this == None(); }
+ bool IsAny() { return this == Any(); }
+ bool IsBitset() { return Config::is_bitset(this); }
+ bool IsUnion() { return Config::is_struct(this, StructuralType::kUnionTag); }
+
+ int AsBitset() {
+ ASSERT(this->IsBitset());
+ return static_cast<BitsetType*>(this)->Bitset();
+ }
+ UnionType* AsUnion() { return UnionType::cast(this); }
+
+ bool SlowIs(TypeImpl* that);
+
+ bool InUnion(UnionHandle unioned, int current_size);
+ static int ExtendUnion(
+ UnionHandle unioned, TypeHandle t, int current_size);
+ static int ExtendIntersection(
+ UnionHandle unioned, TypeHandle t, TypeHandle other, int current_size);
+
+ int BitsetGlb() { return BitsetType::Glb(this); }
+ int BitsetLub() { return BitsetType::Lub(this); }
+};
+
+
+template<class Config>
+class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
+ private:
+ friend class TypeImpl<Config>;
enum {
#define DECLARE_TYPE(type, value) k##type = (value),
@@ -354,52 +403,187 @@
kUnusedEOL = 0
};
- bool IsNone() { return this == None(); }
- bool IsAny() { return this == Any(); }
- bool IsBitset() { return Config::is_bitset(this); }
- bool IsStruct(Tag tag) {
- return Config::is_struct(this)
- && Config::struct_tag(Config::as_struct(this)) == tag;
- }
- bool IsUnion() { return IsStruct(kUnionTag); }
+ int Bitset() { return Config::as_bitset(this); }
- int AsBitset() { return Config::as_bitset(this); }
- StructHandle AsStruct(Tag tag) {
- ASSERT(IsStruct(tag));
- return Config::as_struct(this);
+ static BitsetType* New(int bitset) {
+ return static_cast<BitsetType*>(Config::from_bitset(bitset));
}
- StructHandle AsUnion() { return AsStruct(kUnionTag); }
-
- static int StructLength(StructHandle structured) {
- return Config::struct_length(structured);
+ static TypeHandle New(int bitset, Region* region) {
+ return Config::from_bitset(bitset, region);
}
- static TypeHandle StructGet(StructHandle structured, int i) {
- return Config::struct_get(structured, i);
- }
-
- bool SlowIs(TypeImpl* that);
static bool IsInhabited(int bitset) {
return (bitset & kRepresentation) && (bitset & kSemantic);
}
- int LubBitset(); // least upper bound that's a bitset
- int GlbBitset(); // greatest lower bound that's a bitset
+ static int Glb(TypeImpl* type); // greatest lower bound that's a bitset
+ static int Lub(TypeImpl* type); // least upper bound that's a bitset
+ static int Lub(i::Object* value);
+ static int Lub(i::Map* map);
- static int LubBitset(i::Object* value);
- static int LubBitset(i::Map* map);
-
- bool InUnion(StructHandle unioned, int current_size);
- static int ExtendUnion(
- StructHandle unioned, TypeHandle t, int current_size);
- static int ExtendIntersection(
- StructHandle unioned, TypeHandle t, TypeHandle other, int current_size);
-
- static const char* bitset_name(int bitset);
+ static const char* Name(int bitset);
static void BitsetTypePrint(FILE* out, int bitset);
};
+// Internal
+// A structured type contains a tag and a variable number of type fields.
+template<class Config>
+class TypeImpl<Config>::StructuralType : public TypeImpl<Config> {
+ protected:
+ template<class> friend class TypeImpl;
+ friend struct ZoneTypeConfig; // For tags.
+ friend struct HeapTypeConfig;
+
+ enum Tag {
+ kClassTag,
+ kConstantTag,
+ kArrayTag,
+ kFunctionTag,
+ kUnionTag
+ };
+
+ int Length() {
+ return Config::struct_length(Config::as_struct(this));
+ }
+ TypeHandle Get(int i) {
+ return Config::struct_get(Config::as_struct(this), i);
+ }
+ void Set(int i, TypeHandle type) {
+ Config::struct_set(Config::as_struct(this), i, type);
+ }
+ void Shrink(int length) {
+ Config::struct_shrink(Config::as_struct(this), length);
+ }
+
+ static TypeHandle New(Tag tag, int length, Region* region) {
+ return Config::from_struct(Config::struct_create(tag, length, region));
+ }
+};
+
+
+template<class Config>
+class TypeImpl<Config>::ClassType : public TypeImpl<Config> {
+ public:
+ i::Handle<i::Map> Map() { return Config::as_class(this); }
+
+ static ClassHandle New(i::Handle<i::Map> map, Region* region) {
+ return Config::template cast<ClassType>(
+ Config::from_class(map, BitsetType::Lub(*map), region));
+ }
+
+ static ClassType* cast(TypeImpl* type) {
+ ASSERT(type->IsClass());
+ return static_cast<ClassType*>(type);
+ }
+};
+
+
+template<class Config>
+class TypeImpl<Config>::ConstantType : public TypeImpl<Config> {
+ public:
+ i::Handle<i::Object> Value() { return Config::as_constant(this); }
+
+ static ConstantHandle New(i::Handle<i::Object> value, Region* region) {
+ return Config::template cast<ConstantType>(
+ Config::from_constant(value, BitsetType::Lub(*value), region));
+ }
+
+ static ConstantType* cast(TypeImpl* type) {
+ ASSERT(type->IsConstant());
+ return static_cast<ConstantType*>(type);
+ }
+};
+
+
+// Internal
+// A union is a structured type with the following invariants:
+// - its length is at least 2
+// - at most one field is a bitset, and it must go into index 0
+// - no field is a union
+template<class Config>
+class TypeImpl<Config>::UnionType : public StructuralType {
+ public:
+ static UnionHandle New(int length, Region* region) {
+ return Config::template cast<UnionType>(
+ StructuralType::New(StructuralType::kUnionTag, length, region));
+ }
+
+ static UnionType* cast(TypeImpl* type) {
+ ASSERT(type->IsUnion());
+ return static_cast<UnionType*>(type);
+ }
+};
+
+
+template<class Config>
+class TypeImpl<Config>::ArrayType : public StructuralType {
+ public:
+ TypeHandle Element() { return this->Get(0); }
+
+ static ArrayHandle New(TypeHandle element, Region* region) {
+ ArrayHandle type = Config::template cast<ArrayType>(
+ StructuralType::New(StructuralType::kArrayTag, 1, region));
+ type->Set(0, element);
+ return type;
+ }
+
+ static ArrayType* cast(TypeImpl* type) {
+ ASSERT(type->IsArray());
+ return static_cast<ArrayType*>(type);
+ }
+};
+
+
+template<class Config>
+class TypeImpl<Config>::FunctionType : public StructuralType {
+ public:
+ int Arity() { return this->Length() - 2; }
+ TypeHandle Result() { return this->Get(0); }
+ TypeHandle Receiver() { return this->Get(1); }
+ TypeHandle Parameter(int i) { return this->Get(2 + i); }
+
+ void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); }
+
+ static FunctionHandle New(
+ TypeHandle result, TypeHandle receiver, int arity, Region* region) {
+ FunctionHandle type = Config::template cast<FunctionType>(
+ StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region));
+ type->Set(0, result);
+ type->Set(1, receiver);
+ return type;
+ }
+
+ static FunctionType* cast(TypeImpl* type) {
+ ASSERT(type->IsFunction());
+ return static_cast<FunctionType*>(type);
+ }
+};
+
+
+template<class Config> template<class T>
+class TypeImpl<Config>::Iterator {
+ public:
+ bool Done() const { return index_ < 0; }
+ i::Handle<T> Current();
+ void Advance();
+
+ private:
+ template<class> friend class TypeImpl;
+
+ Iterator() : index_(-1) {}
+ explicit Iterator(TypeHandle type) : type_(type), index_(-1) {
+ Advance();
+ }
+
+ inline bool matches(TypeHandle type);
+ inline TypeHandle get_type();
+
+ TypeHandle type_;
+ int index_;
+};
+
+
// Zone-allocated types are either (odd) integers to represent bitsets, or
// (even) pointers to structures for everything else.
struct ZoneTypeConfig {
@@ -409,27 +593,33 @@
typedef i::Zone Region;
template<class T> struct Handle { typedef T* type; };
- static inline Type* handle(Type* type);
+ template<class T> static inline T* handle(T* type);
+ template<class T> static inline T* cast(Type* type);
+
static inline bool is_bitset(Type* type);
static inline bool is_class(Type* type);
static inline bool is_constant(Type* type);
- static inline bool is_struct(Type* type);
+ static inline bool is_struct(Type* type, int tag);
+
static inline int as_bitset(Type* type);
static inline Struct* as_struct(Type* type);
static inline i::Handle<i::Map> as_class(Type* type);
static inline i::Handle<i::Object> as_constant(Type* type);
+
static inline Type* from_bitset(int bitset);
static inline Type* from_bitset(int bitset, Zone* zone);
static inline Type* from_struct(Struct* structured);
static inline Type* from_class(i::Handle<i::Map> map, int lub, Zone* zone);
static inline Type* from_constant(
i::Handle<i::Object> value, int lub, Zone* zone);
+
static inline Struct* struct_create(int tag, int length, Zone* zone);
static inline void struct_shrink(Struct* structured, int length);
static inline int struct_tag(Struct* structured);
static inline int struct_length(Struct* structured);
static inline Type* struct_get(Struct* structured, int i);
static inline void struct_set(Struct* structured, int i, Type* type);
+
static inline int lub_bitset(Type* type);
};
@@ -445,15 +635,19 @@
typedef i::Isolate Region;
template<class T> struct Handle { typedef i::Handle<T> type; };
- static inline i::Handle<Type> handle(Type* type);
+ template<class T> static inline i::Handle<T> handle(T* type);
+ template<class T> static inline i::Handle<T> cast(i::Handle<Type> type);
+
static inline bool is_bitset(Type* type);
static inline bool is_class(Type* type);
static inline bool is_constant(Type* type);
- static inline bool is_struct(Type* type);
+ static inline bool is_struct(Type* type, int tag);
+
static inline int as_bitset(Type* type);
static inline i::Handle<i::Map> as_class(Type* type);
static inline i::Handle<i::Object> as_constant(Type* type);
static inline i::Handle<Struct> as_struct(Type* type);
+
static inline Type* from_bitset(int bitset);
static inline i::Handle<Type> from_bitset(int bitset, Isolate* isolate);
static inline i::Handle<Type> from_class(
@@ -461,6 +655,7 @@
static inline i::Handle<Type> from_constant(
i::Handle<i::Object> value, int lub, Isolate* isolate);
static inline i::Handle<Type> from_struct(i::Handle<Struct> structured);
+
static inline i::Handle<Struct> struct_create(
int tag, int length, Isolate* isolate);
static inline void struct_shrink(i::Handle<Struct> structured, int length);
@@ -469,6 +664,7 @@
static inline i::Handle<Type> struct_get(i::Handle<Struct> structured, int i);
static inline void struct_set(
i::Handle<Struct> structured, int i, i::Handle<Type> type);
+
static inline int lub_bitset(Type* type);
};
diff --git a/src/unique.h b/src/unique.h
index 2f6008c..b1b4e97 100644
--- a/src/unique.h
+++ b/src/unique.h
@@ -189,7 +189,7 @@
}
// Compare this set against another set. O(|this|).
- bool Equals(UniqueSet<T>* that) const {
+ bool Equals(const UniqueSet<T>* that) const {
if (that->size_ != this->size_) return false;
for (int i = 0; i < this->size_; i++) {
if (this->array_[i] != that->array_[i]) return false;
@@ -200,7 +200,7 @@
// Check whether this set contains the given element. O(|this|)
// TODO(titzer): use binary search for large sets to make this O(log|this|)
template <typename U>
- bool Contains(Unique<U> elem) const {
+ bool Contains(const Unique<U> elem) const {
for (int i = 0; i < size_; i++) {
if (this->array_[i] == elem) return true;
}
@@ -208,7 +208,7 @@
}
// Check if this set is a subset of the given set. O(|this| + |that|).
- bool IsSubset(UniqueSet<T>* that) const {
+ bool IsSubset(const UniqueSet<T>* that) const {
if (that->size_ < this->size_) return false;
int j = 0;
for (int i = 0; i < this->size_; i++) {
diff --git a/src/v8.cc b/src/v8.cc
index b49e0eb..afe8e4b 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -60,22 +60,8 @@
bool V8::Initialize(Deserializer* des) {
InitializeOncePerProcess();
-
- // The current thread may not yet had entered an isolate to run.
- // Note the Isolate::Current() may be non-null because for various
- // initialization purposes an initializing thread may be assigned an isolate
- // but not actually enter it.
- if (i::Isolate::CurrentPerIsolateThreadData() == NULL) {
- i::Isolate::EnterDefaultIsolate();
- }
-
- ASSERT(i::Isolate::CurrentPerIsolateThreadData() != NULL);
- ASSERT(i::Isolate::CurrentPerIsolateThreadData()->thread_id().Equals(
- i::ThreadId::Current()));
- ASSERT(i::Isolate::CurrentPerIsolateThreadData()->isolate() ==
- i::Isolate::Current());
-
- Isolate* isolate = Isolate::Current();
+ Isolate* isolate = Isolate::UncheckedCurrent();
+ if (isolate == NULL) return true;
if (isolate->IsDead()) return false;
if (isolate->IsInitialized()) return true;
@@ -112,6 +98,7 @@
call_completed_callbacks_ = NULL;
Sampler::TearDown();
+ Serializer::TearDown();
#ifdef V8_USE_DEFAULT_PLATFORM
DefaultPlatform* platform = static_cast<DefaultPlatform*>(platform_);
@@ -186,6 +173,7 @@
void V8::InitializeOncePerProcessImpl() {
FlagList::EnforceFlagImplications();
+ Serializer::InitializeOncePerProcess();
if (FLAG_predictable && FLAG_random_seed == 0) {
// Avoid random seeds in predictable mode.
diff --git a/src/v8conversions.h b/src/v8conversions.h
index b38dde7..eb315b1 100644
--- a/src/v8conversions.h
+++ b/src/v8conversions.h
@@ -75,9 +75,8 @@
SealHandleScope shs(isolate);
if (number->IsSmi()) {
int value = Smi::cast(number)->value();
- ASSERT(
- static_cast<unsigned>(Smi::kMaxValue)
- <= std::numeric_limits<size_t>::max());
+ ASSERT(static_cast<unsigned>(Smi::kMaxValue)
+ <= std::numeric_limits<size_t>::max());
if (value >= 0) {
*result = static_cast<size_t>(value);
return true;
diff --git a/src/v8threads.cc b/src/v8threads.cc
index 1de9d4f..150a9b5 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -74,10 +74,6 @@
isolate_->stack_guard()->ClearThread(access);
isolate_->stack_guard()->InitThread(access);
}
- if (isolate_->IsDefaultIsolate()) {
- // This only enters if not yet entered.
- internal::Isolate::EnterDefaultIsolate();
- }
}
ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
}
@@ -98,9 +94,6 @@
Locker::~Locker() {
ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
if (has_lock_) {
- if (isolate_->IsDefaultIsolate()) {
- isolate_->Exit();
- }
if (top_level_) {
isolate_->thread_manager()->FreeThreadResources();
} else {
@@ -115,9 +108,6 @@
ASSERT(isolate != NULL);
isolate_ = reinterpret_cast<i::Isolate*>(isolate);
ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
- if (isolate_->IsDefaultIsolate()) {
- isolate_->Exit();
- }
isolate_->thread_manager()->ArchiveThread();
isolate_->thread_manager()->Unlock();
}
@@ -127,9 +117,6 @@
ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread());
isolate_->thread_manager()->Lock();
isolate_->thread_manager()->RestoreThread();
- if (isolate_->IsDefaultIsolate()) {
- isolate_->Enter();
- }
}
diff --git a/src/version.cc b/src/version.cc
index 12e2af0..3f38536 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 26
-#define BUILD_NUMBER 15
+#define BUILD_NUMBER 22
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 19bd828..da2db62 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -2953,11 +2953,6 @@
ASSERT(!RelocInfo::IsNone(rmode));
if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
// Don't record external references unless the heap will be serialized.
-#ifdef DEBUG
- if (!Serializer::enabled()) {
- Serializer::TooLateToEnableNow();
- }
-#endif
if (!Serializer::enabled() && !emit_debug_code()) {
return;
}
@@ -2992,16 +2987,17 @@
}
-MaybeObject* Assembler::AllocateConstantPool(Heap* heap) {
+Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
// No out-of-line constant pool support.
- UNREACHABLE();
- return NULL;
+ ASSERT(!FLAG_enable_ool_constant_pool);
+ return isolate->factory()->empty_constant_pool_array();
}
void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
// No out-of-line constant pool support.
- UNREACHABLE();
+ ASSERT(!FLAG_enable_ool_constant_pool);
+ return;
}
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index ebcd532..43475d1 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -1179,7 +1179,7 @@
void RecordComment(const char* msg, bool force = false);
// Allocate a constant pool of the correct size for the generated code.
- MaybeObject* AllocateConstantPool(Heap* heap);
+ Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
// Generate the constant pool for the generated code.
void PopulateConstantPool(ConstantPoolArray* constant_pool);
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index d14a935..19e7b53 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -1017,7 +1017,7 @@
// Out of stack space.
__ Push(Operand(rbp, kFunctionOffset));
__ Push(rax);
- __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
__ bind(&okay);
// End of stack check.
@@ -1322,6 +1322,32 @@
}
+static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
+ Label* stack_overflow) {
+ // ----------- S t a t e -------------
+ // -- rax : actual number of arguments
+ // -- rbx : expected number of arguments
+ // -- rdi: function (passed through to callee)
+ // -----------------------------------
+ // Check the stack for overflow. We are not trying to catch
+ // interruptions (e.g. debug break and preemption) here, so the "real stack
+ // limit" is checked.
+ Label okay;
+ __ LoadRoot(rdx, Heap::kRealStackLimitRootIndex);
+ __ movp(rcx, rsp);
+ // Make rcx the space we have left. The stack might already be overflowed
+ // here which will cause rcx to become negative.
+ __ subp(rcx, rdx);
+ // Make rdx the space we need for the array when it is unrolled onto the
+ // stack.
+ __ movp(rdx, rbx);
+ __ shlp(rdx, Immediate(kPointerSizeLog2));
+ // Check if the arguments will overflow the stack.
+ __ cmpp(rcx, rdx);
+ __ j(less_equal, stack_overflow); // Signed comparison.
+}
+
+
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
__ pushq(rbp);
__ movp(rbp, rsp);
@@ -1367,6 +1393,9 @@
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->arguments_adaptors(), 1);
+ Label stack_overflow;
+ ArgumentsAdaptorStackCheck(masm, &stack_overflow);
+
Label enough, too_few;
__ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
__ cmpp(rax, rbx);
@@ -1439,6 +1468,14 @@
// -------------------------------------------
__ bind(&dont_adapt_arguments);
__ jmp(rdx);
+
+ __ bind(&stack_overflow);
+ {
+ FrameScope frame(masm, StackFrame::MANUAL);
+ EnterArgumentsAdaptorFrame(masm);
+ __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
+ __ int3();
+ }
}
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 11699e9..2e2b975 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -2408,19 +2408,28 @@
}
-void CEntryStub::GenerateCore(MacroAssembler* masm,
- Label* throw_normal_exception,
- Label* throw_termination_exception,
- bool do_gc,
- bool always_allocate_scope) {
- // rax: result parameter for PerformGC, if any.
- // rbx: pointer to C function (C callee-saved).
- // rbp: frame pointer (restored after C call).
- // rsp: stack pointer (restored after C call).
+void CEntryStub::Generate(MacroAssembler* masm) {
+ // rax: number of arguments including receiver
+ // rbx: pointer to C function (C callee-saved)
+ // rbp: frame pointer of calling JS frame (restored after C call)
+ // rsp: stack pointer (restored after C call)
+ // rsi: current context (restored)
+
+ ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
+ // Enter the exit frame that transitions from JavaScript to C++.
+#ifdef _WIN64
+ int arg_stack_space = (result_size_ < 2 ? 2 : 4);
+#else
+ int arg_stack_space = 0;
+#endif
+ __ EnterExitFrame(arg_stack_space, save_doubles_);
+
+ // rbx: pointer to builtin function (C callee-saved).
+ // rbp: frame pointer of exit frame (restored after C call).
+ // rsp: stack pointer (restored after C call).
// r14: number of arguments including receiver (C callee-saved).
- // r15: pointer to the first argument (C callee-saved).
- // This pointer is reused in LeaveExitFrame(), so it is stored in a
- // callee-saved register.
+ // r15: argv pointer (C callee-saved).
// Simple results returned in rax (both AMD64 and Win64 calling conventions).
// Complex results must be written to address passed as first argument.
@@ -2431,25 +2440,6 @@
__ CheckStackAlignment();
}
- if (do_gc) {
- // Pass failure code returned from last attempt as first argument to
- // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the
- // stack is known to be aligned. This function takes one argument which is
- // passed in register.
- __ Move(arg_reg_2, ExternalReference::isolate_address(masm->isolate()));
- __ movp(arg_reg_1, rax);
- __ Move(kScratchRegister,
- ExternalReference::perform_gc_function(masm->isolate()));
- __ call(kScratchRegister);
- }
-
- ExternalReference scope_depth =
- ExternalReference::heap_always_allocate_scope_depth(masm->isolate());
- if (always_allocate_scope) {
- Operand scope_depth_operand = masm->ExternalOperand(scope_depth);
- __ incl(scope_depth_operand);
- }
-
// Call C function.
#ifdef _WIN64
// Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9.
@@ -2480,14 +2470,6 @@
__ call(rbx);
// Result is in rax - do not destroy this register!
- if (always_allocate_scope) {
- Operand scope_depth_operand = masm->ExternalOperand(scope_depth);
- __ decl(scope_depth_operand);
- }
-
- // Check for failure result.
- Label failure_returned;
- STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
#ifdef _WIN64
// If return value is on the stack, pop it to registers.
if (result_size_ > 1) {
@@ -2499,121 +2481,65 @@
__ movq(rdx, Operand(rsp, 7 * kRegisterSize));
}
#endif
- __ leap(rcx, Operand(rax, 1));
- // Lower 2 bits of rcx are 0 iff rax has failure tag.
- __ testl(rcx, Immediate(kFailureTagMask));
- __ j(zero, &failure_returned);
+
+ // Runtime functions should not return 'the hole'. Allowing it to escape may
+ // lead to crashes in the IC code later.
+ if (FLAG_debug_code) {
+ Label okay;
+ __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
+ __ j(not_equal, &okay, Label::kNear);
+ __ int3();
+ __ bind(&okay);
+ }
+
+ // Check result for exception sentinel.
+ Label exception_returned;
+ __ CompareRoot(rax, Heap::kExceptionRootIndex);
+ __ j(equal, &exception_returned);
+
+ ExternalReference pending_exception_address(
+ Isolate::kPendingExceptionAddress, masm->isolate());
+
+ // Check that there is no pending exception, otherwise we
+ // should have returned the exception sentinel.
+ if (FLAG_debug_code) {
+ Label okay;
+ __ LoadRoot(r14, Heap::kTheHoleValueRootIndex);
+ Operand pending_exception_operand =
+ masm->ExternalOperand(pending_exception_address);
+ __ cmpp(r14, pending_exception_operand);
+ __ j(equal, &okay, Label::kNear);
+ __ int3();
+ __ bind(&okay);
+ }
// Exit the JavaScript to C++ exit frame.
__ LeaveExitFrame(save_doubles_);
__ ret(0);
- // Handling of failure.
- __ bind(&failure_returned);
-
- Label retry;
- // If the returned exception is RETRY_AFTER_GC continue at retry label
- STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
- __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
- __ j(zero, &retry, Label::kNear);
+ // Handling of exception.
+ __ bind(&exception_returned);
// Retrieve the pending exception.
- ExternalReference pending_exception_address(
- Isolate::kPendingExceptionAddress, masm->isolate());
Operand pending_exception_operand =
masm->ExternalOperand(pending_exception_address);
__ movp(rax, pending_exception_operand);
// Clear the pending exception.
- pending_exception_operand =
- masm->ExternalOperand(pending_exception_address);
__ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
__ movp(pending_exception_operand, rdx);
// Special handling of termination exceptions which are uncatchable
// by javascript code.
+ Label throw_termination_exception;
__ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
- __ j(equal, throw_termination_exception);
+ __ j(equal, &throw_termination_exception);
// Handle normal exception.
- __ jmp(throw_normal_exception);
-
- // Retry.
- __ bind(&retry);
-}
-
-
-void CEntryStub::Generate(MacroAssembler* masm) {
- // rax: number of arguments including receiver
- // rbx: pointer to C function (C callee-saved)
- // rbp: frame pointer of calling JS frame (restored after C call)
- // rsp: stack pointer (restored after C call)
- // rsi: current context (restored)
-
- // NOTE: Invocations of builtins may return failure objects
- // instead of a proper result. The builtin entry handles
- // this by performing a garbage collection and retrying the
- // builtin once.
-
- ProfileEntryHookStub::MaybeCallEntryHook(masm);
-
- // Enter the exit frame that transitions from JavaScript to C++.
-#ifdef _WIN64
- int arg_stack_space = (result_size_ < 2 ? 2 : 4);
-#else
- int arg_stack_space = 0;
-#endif
- __ EnterExitFrame(arg_stack_space, save_doubles_);
-
- // rax: Holds the context at this point, but should not be used.
- // On entry to code generated by GenerateCore, it must hold
- // a failure result if the collect_garbage argument to GenerateCore
- // is true. This failure result can be the result of code
- // generated by a previous call to GenerateCore. The value
- // of rax is then passed to Runtime::PerformGC.
- // rbx: pointer to builtin function (C callee-saved).
- // rbp: frame pointer of exit frame (restored after C call).
- // rsp: stack pointer (restored after C call).
- // r14: number of arguments including receiver (C callee-saved).
- // r15: argv pointer (C callee-saved).
-
- Label throw_normal_exception;
- Label throw_termination_exception;
-
- // Call into the runtime system.
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- false,
- false);
-
- // Do space-specific GC and retry runtime call.
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- true,
- false);
-
- // Do full GC and retry runtime call one final time.
- Failure* failure = Failure::InternalError();
- __ Move(rax, failure, Assembler::RelocInfoNone());
- GenerateCore(masm,
- &throw_normal_exception,
- &throw_termination_exception,
- true,
- true);
-
- { FrameScope scope(masm, StackFrame::MANUAL);
- __ PrepareCallCFunction(0);
- __ CallCFunction(
- ExternalReference::out_of_memory_function(masm->isolate()), 0);
- }
+ __ Throw(rax);
__ bind(&throw_termination_exception);
__ ThrowUncatchable(rax);
-
- __ bind(&throw_normal_exception);
- __ Throw(rax);
}
@@ -2702,7 +2628,7 @@
ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
isolate);
__ Store(pending_exception, rax);
- __ Move(rax, Failure::Exception(), Assembler::RelocInfoNone());
+ __ LoadRoot(rax, Heap::kExceptionRootIndex);
__ jmp(&exit);
// Invoke: Link this frame into the handler chain. There's only one
@@ -3620,202 +3546,6 @@
}
-void ArrayPushStub::Generate(MacroAssembler* masm) {
- int argc = arguments_count();
-
- StackArgumentsAccessor args(rsp, argc);
- if (argc == 0) {
- // Noop, return the length.
- __ movp(rax, FieldOperand(rdx, JSArray::kLengthOffset));
- __ ret((argc + 1) * kPointerSize);
- return;
- }
-
- Isolate* isolate = masm->isolate();
-
- if (argc != 1) {
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- Label call_builtin, attempt_to_grow_elements, with_write_barrier;
-
- // Get the elements array of the object.
- __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
-
- if (IsFastSmiOrObjectElementsKind(elements_kind())) {
- // Check that the elements are in fast mode and writable.
- __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
- isolate->factory()->fixed_array_map());
- __ j(not_equal, &call_builtin);
- }
-
- // Get the array's length into rax and calculate new length.
- __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
- STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
- __ addl(rax, Immediate(argc));
-
- // Get the elements' length into rcx.
- __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
-
- // Check if we could survive without allocation.
- __ cmpl(rax, rcx);
-
- if (IsFastSmiOrObjectElementsKind(elements_kind())) {
- __ j(greater, &attempt_to_grow_elements);
-
- // Check if value is a smi.
- __ movp(rcx, args.GetArgumentOperand(1));
- __ JumpIfNotSmi(rcx, &with_write_barrier);
-
- // Store the value.
- __ movp(FieldOperand(rdi,
- rax,
- times_pointer_size,
- FixedArray::kHeaderSize - argc * kPointerSize),
- rcx);
- } else {
- __ j(greater, &call_builtin);
-
- __ movp(rcx, args.GetArgumentOperand(1));
- __ StoreNumberToDoubleElements(
- rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize);
- }
-
- // Save new length.
- __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
-
- __ Integer32ToSmi(rax, rax); // Return new length as smi.
- __ ret((argc + 1) * kPointerSize);
-
- if (IsFastDoubleElementsKind(elements_kind())) {
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- __ bind(&with_write_barrier);
-
- if (IsFastSmiElementsKind(elements_kind())) {
- if (FLAG_trace_elements_transitions) __ jmp(&call_builtin);
-
- __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset),
- isolate->factory()->heap_number_map());
- __ j(equal, &call_builtin);
-
- ElementsKind target_kind = IsHoleyElementsKind(elements_kind())
- ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
- __ movp(rbx, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX));
- __ movp(rbx, FieldOperand(rbx, GlobalObject::kNativeContextOffset));
- __ movp(rbx, ContextOperand(rbx, Context::JS_ARRAY_MAPS_INDEX));
- const int header_size = FixedArrayBase::kHeaderSize;
- // Verify that the object can be transitioned in place.
- const int origin_offset = header_size + elements_kind() * kPointerSize;
- __ movp(rdi, FieldOperand(rbx, origin_offset));
- __ cmpp(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
- __ j(not_equal, &call_builtin);
-
- const int target_offset = header_size + target_kind * kPointerSize;
- __ movp(rbx, FieldOperand(rbx, target_offset));
- ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
- masm, DONT_TRACK_ALLOCATION_SITE, NULL);
- __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
- }
-
- // Save new length.
- __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
-
- // Store the value.
- __ leap(rdx, FieldOperand(rdi,
- rax, times_pointer_size,
- FixedArray::kHeaderSize - argc * kPointerSize));
- __ movp(Operand(rdx, 0), rcx);
-
- __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
-
- __ Integer32ToSmi(rax, rax); // Return new length as smi.
- __ ret((argc + 1) * kPointerSize);
-
- __ bind(&attempt_to_grow_elements);
- if (!FLAG_inline_new) {
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
- return;
- }
-
- __ movp(rbx, args.GetArgumentOperand(1));
- // Growing elements that are SMI-only requires special handling in case the
- // new element is non-Smi. For now, delegate to the builtin.
- Label no_fast_elements_check;
- __ JumpIfSmi(rbx, &no_fast_elements_check);
- __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
- __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar);
- __ bind(&no_fast_elements_check);
-
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate);
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate);
-
- const int kAllocationDelta = 4;
- ASSERT(kAllocationDelta >= argc);
- // Load top.
- __ Load(rcx, new_space_allocation_top);
-
- // Check if it's the end of elements.
- __ leap(rdx, FieldOperand(rdi,
- rax, times_pointer_size,
- FixedArray::kHeaderSize - argc * kPointerSize));
- __ cmpp(rdx, rcx);
- __ j(not_equal, &call_builtin);
- __ addp(rcx, Immediate(kAllocationDelta * kPointerSize));
- Operand limit_operand = masm->ExternalOperand(new_space_allocation_limit);
- __ cmpp(rcx, limit_operand);
- __ j(above, &call_builtin);
-
- // We fit and could grow elements.
- __ Store(new_space_allocation_top, rcx);
-
- // Push the argument...
- __ movp(Operand(rdx, 0), rbx);
- // ... and fill the rest with holes.
- __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
- for (int i = 1; i < kAllocationDelta; i++) {
- __ movp(Operand(rdx, i * kPointerSize), kScratchRegister);
- }
-
- if (IsFastObjectElementsKind(elements_kind())) {
- // We know the elements array is in new space so we don't need the
- // remembered set, but we just pushed a value onto it so we may have to tell
- // the incremental marker to rescan the object that we just grew. We don't
- // need to worry about the holes because they are in old space and already
- // marked black.
- __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
- }
-
- // Restore receiver to rdx as finish sequence assumes it's here.
- __ movp(rdx, args.GetReceiverOperand());
-
- // Increment element's and array's sizes.
- __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset),
- Smi::FromInt(kAllocationDelta));
-
- // Make new length a smi before returning it.
- __ Integer32ToSmi(rax, rax);
- __ movp(FieldOperand(rdx, JSArray::kLengthOffset), rax);
-
- __ ret((argc + 1) * kPointerSize);
-
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
-}
-
-
void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rdx : left
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 1d5480f..44ffc29 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -74,7 +74,7 @@
void EmitPatchInfo() {
if (patch_site_.is_bound()) {
int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
- ASSERT(is_int8(delta_to_patch_site));
+ ASSERT(is_uint8(delta_to_patch_site));
__ testl(rax, Immediate(delta_to_patch_site));
#ifdef DEBUG
info_emitted_ = true;
@@ -363,6 +363,9 @@
}
+static const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14;
+
+
void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
Label* back_edge_target) {
Comment cmnt(masm_, "[ Back edge bookkeeping");
@@ -373,17 +376,22 @@
int weight = Min(kMaxBackEdgeWeight,
Max(1, distance / kCodeSizeMultiplier));
EmitProfilingCounterDecrement(weight);
+
__ j(positive, &ok, Label::kNear);
- __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
+ {
+ PredictableCodeSizeScope predictible_code_size_scope(masm_, kJnsOffset);
+ DontEmitDebugCodeScope dont_emit_debug_code_scope(masm_);
+ __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
- // Record a mapping of this PC offset to the OSR id. This is used to find
- // the AST id from the unoptimized code in order to use it as a key into
- // the deoptimization input data found in the optimized code.
- RecordBackEdge(stmt->OsrEntryId());
+ // Record a mapping of this PC offset to the OSR id. This is used to find
+ // the AST id from the unoptimized code in order to use it as a key into
+ // the deoptimization input data found in the optimized code.
+ RecordBackEdge(stmt->OsrEntryId());
- EmitProfilingCounterReset();
-
+ EmitProfilingCounterReset();
+ }
__ bind(&ok);
+
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
// Record a mapping of the OSR id to this PC. This is used if the OSR
// entry becomes the target of a bailout. We don't expect it to be, but
@@ -2256,7 +2264,7 @@
Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->generator_result_map());
+ Handle<Map> map(isolate()->native_context()->iterator_result_map());
__ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT);
__ jmp(&allocated);
@@ -4844,7 +4852,6 @@
static const byte kJnsInstruction = 0x79;
-static const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14;
static const byte kNopByteOne = 0x66;
static const byte kNopByteTwo = 0x90;
#ifdef DEBUG
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index b998e0d..cf23462 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -1303,7 +1303,7 @@
Address delta_address = test_instruction_address + 1;
// The delta to the start of the map check instruction and the
// condition code uses at the patched jump.
- int8_t delta = *reinterpret_cast<int8_t*>(delta_address);
+ uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
if (FLAG_trace_ic) {
PrintF("[ patching ic at %p, test=%p, delta=%d\n",
address, test_instruction_address, delta);
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 89f7cd0..0cc8d16 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -4037,7 +4037,7 @@
Condition cc = masm()->CheckSmi(value);
DeoptimizeIf(cc, instr->environment());
- // We know that value is a smi now, so we can omit the check below.
+ // We know now that value is not a smi, so we can omit the check below.
check_needed = OMIT_SMI_CHECK;
}
}
@@ -4140,68 +4140,67 @@
}
-void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) {
- if (FLAG_debug_code && check->hydrogen()->skip_check()) {
+void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
+ Representation representation = instr->hydrogen()->length()->representation();
+ ASSERT(representation.Equals(instr->hydrogen()->index()->representation()));
+ ASSERT(representation.IsSmiOrInteger32());
+
+ Condition cc = instr->hydrogen()->allow_equality() ? below : below_equal;
+ if (instr->length()->IsConstantOperand()) {
+ int32_t length = ToInteger32(LConstantOperand::cast(instr->length()));
+ Register index = ToRegister(instr->index());
+ if (representation.IsSmi()) {
+ __ Cmp(index, Smi::FromInt(length));
+ } else {
+ __ cmpl(index, Immediate(length));
+ }
+ cc = ReverseCondition(cc);
+ } else if (instr->index()->IsConstantOperand()) {
+ int32_t index = ToInteger32(LConstantOperand::cast(instr->index()));
+ if (instr->length()->IsRegister()) {
+ Register length = ToRegister(instr->length());
+ if (representation.IsSmi()) {
+ __ Cmp(length, Smi::FromInt(index));
+ } else {
+ __ cmpl(length, Immediate(index));
+ }
+ } else {
+ Operand length = ToOperand(instr->length());
+ if (representation.IsSmi()) {
+ __ Cmp(length, Smi::FromInt(index));
+ } else {
+ __ cmpl(length, Immediate(index));
+ }
+ }
+ } else {
+ Register index = ToRegister(instr->index());
+ if (instr->length()->IsRegister()) {
+ Register length = ToRegister(instr->length());
+ if (representation.IsSmi()) {
+ __ cmpp(length, index);
+ } else {
+ __ cmpl(length, index);
+ }
+ } else {
+ Operand length = ToOperand(instr->length());
+ if (representation.IsSmi()) {
+ __ cmpp(length, index);
+ } else {
+ __ cmpl(length, index);
+ }
+ }
+ }
+ if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
Label done;
__ j(NegateCondition(cc), &done, Label::kNear);
__ int3();
__ bind(&done);
} else {
- DeoptimizeIf(cc, check->environment());
+ DeoptimizeIf(cc, instr->environment());
}
}
-void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
- HBoundsCheck* hinstr = instr->hydrogen();
- if (hinstr->skip_check()) return;
-
- Representation representation = hinstr->length()->representation();
- ASSERT(representation.Equals(hinstr->index()->representation()));
- ASSERT(representation.IsSmiOrInteger32());
-
- if (instr->length()->IsRegister()) {
- Register reg = ToRegister(instr->length());
-
- if (instr->index()->IsConstantOperand()) {
- int32_t constant_index =
- ToInteger32(LConstantOperand::cast(instr->index()));
- if (representation.IsSmi()) {
- __ Cmp(reg, Smi::FromInt(constant_index));
- } else {
- __ cmpl(reg, Immediate(constant_index));
- }
- } else {
- Register reg2 = ToRegister(instr->index());
- if (representation.IsSmi()) {
- __ cmpp(reg, reg2);
- } else {
- __ cmpl(reg, reg2);
- }
- }
- } else {
- Operand length = ToOperand(instr->length());
- if (instr->index()->IsConstantOperand()) {
- int32_t constant_index =
- ToInteger32(LConstantOperand::cast(instr->index()));
- if (representation.IsSmi()) {
- __ Cmp(length, Smi::FromInt(constant_index));
- } else {
- __ cmpl(length, Immediate(constant_index));
- }
- } else {
- if (representation.IsSmi()) {
- __ cmpp(length, ToRegister(instr->index()));
- } else {
- __ cmpl(length, ToRegister(instr->index()));
- }
- }
- }
- Condition condition = hinstr->allow_equality() ? below : below_equal;
- ApplyCheckIf(condition, instr);
-}
-
-
void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
LOperand* key = instr->key();
@@ -5052,15 +5051,15 @@
__ bind(deferred->check_maps());
}
- UniqueSet<Map> map_set = instr->hydrogen()->map_set();
+ const UniqueSet<Map>* map_set = instr->hydrogen()->map_set();
Label success;
- for (int i = 0; i < map_set.size() - 1; i++) {
- Handle<Map> map = map_set.at(i).handle();
+ for (int i = 0; i < map_set->size() - 1; i++) {
+ Handle<Map> map = map_set->at(i).handle();
__ CompareMap(reg, map);
__ j(equal, &success, Label::kNear);
}
- Handle<Map> map = map_set.at(map_set.size() - 1).handle();
+ Handle<Map> map = map_set->at(map_set->size() - 1).handle();
__ CompareMap(reg, map);
if (instr->hydrogen()->has_migration_target()) {
__ j(not_equal, deferred->entry());
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index 23c63c8..604c360 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -227,7 +227,6 @@
LEnvironment* environment,
Deoptimizer::BailoutType bailout_type);
void DeoptimizeIf(Condition cc, LEnvironment* environment);
- void ApplyCheckIf(Condition cc, LBoundsCheck* check);
bool DeoptEveryNTimes() {
return FLAG_deopt_every_n_times != 0 && !info()->IsStub();
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index e82e6e8..256268b 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -1621,6 +1621,8 @@
LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
HCompareNumericAndBranch* instr) {
+ LInstruction* goto_instr = CheckElideControlInstruction(instr);
+ if (goto_instr != NULL) return goto_instr;
Representation r = instr->representation();
if (r.IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(r));
@@ -1789,9 +1791,16 @@
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
- LOperand* value = UseRegisterOrConstantAtStart(instr->index());
- LOperand* length = Use(instr->length());
- return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
+ if (!FLAG_debug_code && instr->skip_check()) return NULL;
+ LOperand* index = UseRegisterOrConstantAtStart(instr->index());
+ LOperand* length = !index->IsConstantOperand()
+ ? UseOrConstantAtStart(instr->length())
+ : UseAtStart(instr->length());
+ LInstruction* result = new(zone()) LBoundsCheck(index, length);
+ if (!FLAG_debug_code || !instr->skip_check()) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index b36f4f0..1fd7c2c 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -54,10 +54,10 @@
}
-static const int kInvalidRootRegisterDelta = -1;
+static const int64_t kInvalidRootRegisterDelta = -1;
-intptr_t MacroAssembler::RootRegisterDelta(ExternalReference other) {
+int64_t MacroAssembler::RootRegisterDelta(ExternalReference other) {
if (predictable_code_size() &&
(other.address() < reinterpret_cast<Address>(isolate()) ||
other.address() >= reinterpret_cast<Address>(isolate() + 1))) {
@@ -65,7 +65,18 @@
}
Address roots_register_value = kRootRegisterBias +
reinterpret_cast<Address>(isolate()->heap()->roots_array_start());
- intptr_t delta = other.address() - roots_register_value;
+
+ int64_t delta = kInvalidRootRegisterDelta; // Bogus initialization.
+ if (kPointerSize == kInt64Size) {
+ delta = other.address() - roots_register_value;
+ } else {
+ // For x32, zero extend the address to 64-bit and calculate the delta.
+ uint64_t o = static_cast<uint32_t>(
+ reinterpret_cast<intptr_t>(other.address()));
+ uint64_t r = static_cast<uint32_t>(
+ reinterpret_cast<intptr_t>(roots_register_value));
+ delta = o - r;
+ }
return delta;
}
@@ -73,9 +84,8 @@
Operand MacroAssembler::ExternalOperand(ExternalReference target,
Register scratch) {
if (root_array_available_ && !Serializer::enabled()) {
- intptr_t delta = RootRegisterDelta(target);
+ int64_t delta = RootRegisterDelta(target);
if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
- Serializer::TooLateToEnableNow();
return Operand(kRootRegister, static_cast<int32_t>(delta));
}
}
@@ -86,9 +96,8 @@
void MacroAssembler::Load(Register destination, ExternalReference source) {
if (root_array_available_ && !Serializer::enabled()) {
- intptr_t delta = RootRegisterDelta(source);
+ int64_t delta = RootRegisterDelta(source);
if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
- Serializer::TooLateToEnableNow();
movp(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
return;
}
@@ -105,9 +114,8 @@
void MacroAssembler::Store(ExternalReference destination, Register source) {
if (root_array_available_ && !Serializer::enabled()) {
- intptr_t delta = RootRegisterDelta(destination);
+ int64_t delta = RootRegisterDelta(destination);
if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
- Serializer::TooLateToEnableNow();
movp(Operand(kRootRegister, static_cast<int32_t>(delta)), source);
return;
}
@@ -125,9 +133,8 @@
void MacroAssembler::LoadAddress(Register destination,
ExternalReference source) {
if (root_array_available_ && !Serializer::enabled()) {
- intptr_t delta = RootRegisterDelta(source);
+ int64_t delta = RootRegisterDelta(source);
if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
- Serializer::TooLateToEnableNow();
leap(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
return;
}
@@ -142,9 +149,8 @@
// This calculation depends on the internals of LoadAddress.
// It's correctness is ensured by the asserts in the Call
// instruction below.
- intptr_t delta = RootRegisterDelta(source);
+ int64_t delta = RootRegisterDelta(source);
if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
- Serializer::TooLateToEnableNow();
// Operand is leap(scratch, Operand(kRootRegister, delta));
// Opcodes : REX.W 8D ModRM Disp8/Disp32 - 4 or 7.
int size = 4;
@@ -1335,8 +1341,15 @@
return CheckSmi(first);
}
STATIC_ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
- leal(kScratchRegister, Operand(first, second, times_1, 0));
- testb(kScratchRegister, Immediate(0x03));
+ if (SmiValuesAre32Bits()) {
+ leal(kScratchRegister, Operand(first, second, times_1, 0));
+ testb(kScratchRegister, Immediate(0x03));
+ } else {
+ ASSERT(SmiValuesAre31Bits());
+ movl(kScratchRegister, first);
+ orl(kScratchRegister, second);
+ testb(kScratchRegister, Immediate(kSmiTagMask));
+ }
return zero;
}
@@ -1382,16 +1395,28 @@
Condition MacroAssembler::CheckInteger32ValidSmiValue(Register src) {
- // A 32-bit integer value can always be converted to a smi.
- return always;
+ if (SmiValuesAre32Bits()) {
+ // A 32-bit integer value can always be converted to a smi.
+ return always;
+ } else {
+ ASSERT(SmiValuesAre31Bits());
+ cmpl(src, Immediate(0xc0000000));
+ return positive;
+ }
}
Condition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) {
- // An unsigned 32-bit integer value is valid as long as the high bit
- // is not set.
- testl(src, src);
- return positive;
+ if (SmiValuesAre32Bits()) {
+ // An unsigned 32-bit integer value is valid as long as the high bit
+ // is not set.
+ testl(src, src);
+ return positive;
+ } else {
+ ASSERT(SmiValuesAre31Bits());
+ testl(src, Immediate(0xc0000000));
+ return zero;
+ }
}
@@ -1534,7 +1559,13 @@
void MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
if (constant->value() != 0) {
- addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value()));
+ if (SmiValuesAre32Bits()) {
+ addl(Operand(dst, kSmiShift / kBitsPerByte),
+ Immediate(constant->value()));
+ } else {
+ ASSERT(SmiValuesAre31Bits());
+ addp(dst, Immediate(constant));
+ }
}
}
@@ -1992,8 +2023,14 @@
void MacroAssembler::SmiNot(Register dst, Register src) {
ASSERT(!dst.is(kScratchRegister));
ASSERT(!src.is(kScratchRegister));
- // Set tag and padding bits before negating, so that they are zero afterwards.
- movl(kScratchRegister, Immediate(~0));
+ if (SmiValuesAre32Bits()) {
+ // Set tag and padding bits before negating, so that they are zero
+ // afterwards.
+ movl(kScratchRegister, Immediate(~0));
+ } else {
+ ASSERT(SmiValuesAre31Bits());
+ movl(kScratchRegister, Immediate(1));
+ }
if (dst.is(src)) {
xorp(dst, kScratchRegister);
} else {
@@ -2267,8 +2304,14 @@
void MacroAssembler::AddSmiField(Register dst, const Operand& src) {
- ASSERT_EQ(0, kSmiShift % kBitsPerByte);
- addl(dst, Operand(src, kSmiShift / kBitsPerByte));
+ if (SmiValuesAre32Bits()) {
+ ASSERT_EQ(0, kSmiShift % kBitsPerByte);
+ addl(dst, Operand(src, kSmiShift / kBitsPerByte));
+ } else {
+ ASSERT(SmiValuesAre31Bits());
+ SmiToInteger32(kScratchRegister, src);
+ addl(dst, kScratchRegister);
+ }
}
@@ -2310,7 +2353,12 @@
void MacroAssembler::Test(const Operand& src, Smi* source) {
- testl(Operand(src, kIntSize), Immediate(source->value()));
+ if (SmiValuesAre32Bits()) {
+ testl(Operand(src, kIntSize), Immediate(source->value()));
+ } else {
+ ASSERT(SmiValuesAre31Bits());
+ testl(src, Immediate(source));
+ }
}
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 4a2fa8e..a216364 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -1465,7 +1465,7 @@
// modified. It may be the "smi 1 constant" register.
Register GetSmiConstant(Smi* value);
- intptr_t RootRegisterDelta(ExternalReference other);
+ int64_t RootRegisterDelta(ExternalReference other);
// Moves the smi value to the destination register.
void LoadSmiConstant(Register dst, Smi* value);
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 807e00b..d488f5b 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -1233,7 +1233,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
+ Object* result = Execution::HandleStackGuardInterrupt(isolate);
if (*code_handle != re_code) { // Return address no longer valid
intptr_t delta = code_handle->address() - re_code->address();
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 13e822d..93121a0 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -495,6 +495,21 @@
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
+ HeapType* field_type = descriptors->GetFieldType(descriptor);
+ HeapType::Iterator<Map> it = field_type->Classes();
+ if (!it.Done()) {
+ Label do_store;
+ while (true) {
+ __ CompareMap(value_reg, it.Current());
+ it.Advance();
+ if (it.Done()) {
+ __ j(not_equal, miss_label);
+ break;
+ }
+ __ j(equal, &do_store, Label::kNear);
+ }
+ __ bind(&do_store);
+ }
} else if (representation.IsDouble()) {
Label do_store, heap_number;
__ AllocateHeapNumber(storage_reg, scratch1, slow);
@@ -639,6 +654,21 @@
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
+ HeapType* field_type = lookup->GetFieldType();
+ HeapType::Iterator<Map> it = field_type->Classes();
+ if (!it.Done()) {
+ Label do_store;
+ while (true) {
+ __ CompareMap(value_reg, it.Current());
+ it.Advance();
+ if (it.Done()) {
+ __ j(not_equal, miss_label);
+ break;
+ }
+ __ j(equal, &do_store, Label::kNear);
+ }
+ __ bind(&do_store);
+ }
} else if (representation.IsDouble()) {
// Load the double storage.
if (index < 0) {
@@ -741,7 +771,9 @@
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
- if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
+ if (type->IsConstant()) {
+ current = Handle<JSObject>::cast(type->AsConstant()->Value());
+ }
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> holder_map(holder->map());
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index eba0580..745b4c5 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -41,7 +41,7 @@
'include_dirs': [
'../../src',
],
- 'sources': [
+ 'sources': [ ### gcmole(all) ###
'<(generated_file)',
'cctest.cc',
'gay-fixed.cc',
@@ -125,7 +125,7 @@
],
'conditions': [
['v8_target_arch=="ia32"', {
- 'sources': [
+ 'sources': [ ### gcmole(arch:ia32) ###
'test-assembler-ia32.cc',
'test-code-stubs.cc',
'test-code-stubs-ia32.cc',
@@ -136,7 +136,7 @@
],
}],
['v8_target_arch=="x64"', {
- 'sources': [
+ 'sources': [ ### gcmole(arch:x64) ###
'test-assembler-x64.cc',
'test-code-stubs.cc',
'test-code-stubs-x64.cc',
@@ -147,7 +147,7 @@
],
}],
['v8_target_arch=="arm"', {
- 'sources': [
+ 'sources': [ ### gcmole(arch:arm) ###
'test-assembler-arm.cc',
'test-code-stubs.cc',
'test-code-stubs-arm.cc',
@@ -156,7 +156,7 @@
],
}],
['v8_target_arch=="arm64"', {
- 'sources': [
+ 'sources': [ ### gcmole(arch:arm64) ###
'test-utils-arm64.cc',
'test-assembler-arm64.cc',
'test-code-stubs.cc',
@@ -168,7 +168,7 @@
],
}],
['v8_target_arch=="mipsel"', {
- 'sources': [
+ 'sources': [ ### gcmole(arch:mipsel) ###
'test-assembler-mips.cc',
'test-code-stubs.cc',
'test-code-stubs-mips.cc',
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index c8f9370..c00bf3a 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -186,7 +186,7 @@
}], # 'arch == arm'
##############################################################################
-['arch == mipsel', {
+['arch == mipsel or arch == mips', {
# BUG(2657): Test sometimes times out on MIPS simulator.
'test-thread-termination/TerminateMultipleV8ThreadsDefaultIsolate': [PASS, TIMEOUT],
@@ -196,7 +196,7 @@
'test-serialize/DeserializeFromSecondSerializationAndRunScript2': [SKIP],
'test-serialize/DeserializeAndRunScript2': [SKIP],
'test-serialize/DeserializeFromSecondSerialization': [SKIP],
-}], # 'arch == mipsel'
+}], # 'arch == mipsel or arch == mips'
##############################################################################
['arch == android_arm or arch == android_ia32', {
diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc
index a4e4865..c1b1cbd 100644
--- a/test/cctest/test-alloc.cc
+++ b/test/cctest/test-alloc.cc
@@ -55,7 +55,7 @@
// Old data space.
SimulateFullSpace(heap->old_data_space());
- CHECK(!heap->AllocateRawOneByteString(100, TENURED)->IsFailure());
+ CHECK(!heap->AllocateByteArray(100, TENURED)->IsFailure());
// Old pointer space.
SimulateFullSpace(heap->old_pointer_space());
@@ -122,8 +122,8 @@
v8::HandleScope scope(CcTest::isolate());
v8::Handle<v8::Context> env = v8::Context::New(CcTest::isolate());
env->Enter();
- Handle<JSFunction> function =
- factory->NewFunction(factory->function_string(), factory->null_value());
+ Handle<JSFunction> function = factory->NewFunctionWithPrototype(
+ factory->function_string(), factory->null_value());
// Force the creation of an initial map and set the code to
// something empty.
factory->NewJSObject(function);
@@ -133,8 +133,7 @@
Handle<Map> map(function->initial_map());
Handle<DescriptorArray> instance_descriptors(map->instance_descriptors());
Handle<Foreign> foreign = factory->NewForeign(&kDescriptor);
- Handle<String> name =
- factory->NewStringFromAscii(Vector<const char>("get", 3));
+ Handle<String> name = factory->NewStringFromStaticAscii("get");
ASSERT(instance_descriptors->IsEmpty());
Map::EnsureDescriptorSlack(map, 1);
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 3f6351c..e90dd4e 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -19523,7 +19523,7 @@
case SetResourceConstraints: {
static const int K = 1024;
v8::ResourceConstraints constraints;
- constraints.set_max_young_space_size(256 * K);
+ constraints.set_max_new_space_size(256 * K);
constraints.set_max_old_space_size(4 * K * K);
v8::SetResourceConstraints(CcTest::isolate(), &constraints);
break;
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc
index 7a3dec5..470cd61 100644
--- a/test/cctest/test-assembler-arm.cc
+++ b/test/cctest/test-assembler-arm.cc
@@ -57,15 +57,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
+ F2 f = FUNCTION_CAST<F2>(code->entry());
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
::printf("f() = %d\n", res);
CHECK_EQ(7, res);
@@ -95,15 +92,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+ F1 f = FUNCTION_CAST<F1>(code->entry());
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
::printf("f() = %d\n", res);
CHECK_EQ(5050, res);
@@ -142,15 +136,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+ F1 f = FUNCTION_CAST<F1>(code->entry());
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
::printf("f() = %d\n", res);
CHECK_EQ(3628800, res);
@@ -191,15 +182,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.i = 100000;
t.c = 10;
t.s = 1000;
@@ -317,15 +305,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.a = 1.5;
t.b = 2.75;
t.c = 17.17;
@@ -380,15 +365,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+ F1 f = FUNCTION_CAST<F1>(code->entry());
int res = reinterpret_cast<int>(
CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0));
::printf("f() = %d\n", res);
@@ -416,15 +398,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+ F1 f = FUNCTION_CAST<F1>(code->entry());
int res = reinterpret_cast<int>(
CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0));
::printf("f() = %d\n", res);
@@ -492,15 +471,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+ F1 f = FUNCTION_CAST<F1>(code->entry());
int res = reinterpret_cast<int>(
CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
::printf("res = %d\n", res);
@@ -678,15 +654,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
+ F4 fn = FUNCTION_CAST<F4>(code->entry());
d.a = 1.1;
d.b = 2.2;
d.c = 3.3;
@@ -790,15 +763,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
+ F4 fn = FUNCTION_CAST<F4>(code->entry());
d.a = 1.1;
d.b = 2.2;
d.c = 3.3;
@@ -898,15 +868,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
+ F4 fn = FUNCTION_CAST<F4>(code->entry());
d.a = 1.1;
d.b = 2.2;
d.c = 3.3;
@@ -995,15 +962,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
USE(dummy);
@@ -1125,15 +1089,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.a = 1.5;
t.b = 2.75;
t.c = 17.17;
@@ -1200,15 +1161,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.left = BitCast<double>(kHoleNanInt64);
t.right = 1;
t.add_result = 0;
@@ -1306,15 +1264,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.src0 = 0x01020304;
t.src1 = 0x11121314;
t.src2 = 0x21222324;
@@ -1411,15 +1366,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.src0 = 0x01020304;
t.src1 = 0x11121314;
t.src2 = 0x11121300;
@@ -1496,15 +1448,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- Code::cast(code)->Print();
+ code->Print();
#endif
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
Object* dummy;
TEST_SDIV(1073741824, kMinInt, -2);
TEST_SDIV(kMinInt, kMinInt, -1);
@@ -1586,9 +1535,8 @@
CodeDesc desc;
assm.GetCode(&desc);
- Handle<Code> code = isolate->factory()->NewCode(desc,
- Code::ComputeFlags(Code::STUB), code_object);
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), code_object);
F1 f = FUNCTION_CAST<F1>(code->entry());
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 21, 0, 0, 0, 0));
::printf("f() = %d\n", res);
diff --git a/test/cctest/test-assembler-arm64.cc b/test/cctest/test-assembler-arm64.cc
index 3264352..a97e575 100644
--- a/test/cctest/test-assembler-arm64.cc
+++ b/test/cctest/test-assembler-arm64.cc
@@ -10937,19 +10937,15 @@
__ bind(&exit);
- Heap* heap = isolate->heap();
+ HandleScope handle_scope(isolate);
CodeDesc desc;
- Object* code_object = NULL;
- Code* code;
masm.GetCode(&desc);
- MaybeObject* maybe_code = heap->CreateCode(desc, 0, masm.CodeObject());
- maybe_code->ToObject(&code_object);
- code = Code::cast(code_object);
+ Handle<Code> code = isolate->factory()->NewCode(desc, 0, masm.CodeObject());
unsigned pool_count = 0;
int pool_mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
- for (RelocIterator it(code, pool_mask); !it.done(); it.next()) {
+ for (RelocIterator it(*code, pool_mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo();
if (RelocInfo::IsConstPool(info->rmode())) {
ASSERT(info->data() == constant_pool_size);
diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc
index db28231..ba83b3d 100644
--- a/test/cctest/test-assembler-ia32.cc
+++ b/test/cctest/test-assembler-ia32.cc
@@ -60,15 +60,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
+ code->Print();
#endif
- F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
+ F2 f = FUNCTION_CAST<F2>(code->entry());
int res = f(3, 4);
::printf("f() = %d\n", res);
CHECK_EQ(7, res);
@@ -99,15 +96,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
+ code->Print();
#endif
- F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+ F1 f = FUNCTION_CAST<F1>(code->entry());
int res = f(100);
::printf("f() = %d\n", res);
CHECK_EQ(5050, res);
@@ -142,15 +136,12 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
+ code->Print();
#endif
- F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+ F1 f = FUNCTION_CAST<F1>(code->entry());
int res = f(10);
::printf("f() = %d\n", res);
CHECK_EQ(3628800, res);
@@ -177,10 +168,8 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
// don't print the code - our disassembler can't handle cvttss2si
// instead print bytes
Disassembler::Dump(stdout,
@@ -212,10 +201,8 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
// don't print the code - our disassembler can't handle cvttsd2si
// instead print bytes
Disassembler::Dump(stdout,
@@ -242,10 +229,8 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F0 f = FUNCTION_CAST<F0>(code->entry());
int res = f();
CHECK_EQ(42, res);
@@ -279,10 +264,8 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
::printf("\n---\n");
// don't print the code - our disassembler can't handle SSE instructions
@@ -319,15 +302,12 @@
__ ret(0);
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
+ code->Print();
#endif
- F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
+ F6 f = FUNCTION_CAST<F6>(code->entry());
double res = f(12);
::printf("f() = %f\n", res);
@@ -375,16 +355,13 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
+ code->Print();
#endif
- F7 f = FUNCTION_CAST<F7>(Code::cast(code)->entry());
+ F7 f = FUNCTION_CAST<F7>(code->entry());
CHECK_EQ(kLess, f(1.1, 2.2));
CHECK_EQ(kEqual, f(2.2, 2.2));
CHECK_EQ(kGreater, f(3.3, 2.2));
@@ -461,10 +438,8 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
CHECK(code->IsCode());
F0 f = FUNCTION_CAST<F0>(code->entry());
@@ -514,13 +489,10 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
- F0 f = FUNCTION_CAST<F0>(Code::cast(code)->entry());
+ F0 f = FUNCTION_CAST<F0>(code->entry());
int res = f();
args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
}
@@ -584,16 +556,13 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
+ code->Print();
#endif
- F4 f = FUNCTION_CAST<F4>(Code::cast(code)->entry());
+ F4 f = FUNCTION_CAST<F4>(code->entry());
uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
CHECK_EQ(0x12345678, f(uint64_to_double(value1)));
uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
@@ -627,16 +596,13 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
+ code->Print();
#endif
- F8 f = FUNCTION_CAST<F8>(Code::cast(code)->entry());
+ F8 f = FUNCTION_CAST<F8>(code->entry());
CHECK_EQ(2, f(1.0, 2.0));
}
diff --git a/test/cctest/test-assembler-mips.cc b/test/cctest/test-assembler-mips.cc
index 534c4cf..e93c1ca 100644
--- a/test/cctest/test-assembler-mips.cc
+++ b/test/cctest/test-assembler-mips.cc
@@ -61,12 +61,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F2 f = FUNCTION_CAST<F2>(code->entry());
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
::printf("f() = %d\n", res);
CHECK_EQ(0xabc, res);
@@ -100,12 +97,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F1 f = FUNCTION_CAST<F1>(code->entry());
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
::printf("f() = %d\n", res);
CHECK_EQ(1275, res);
@@ -241,12 +235,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F2 f = FUNCTION_CAST<F2>(code->entry());
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
::printf("f() = %d\n", res);
CHECK_EQ(0x31415926, res);
@@ -314,12 +305,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.a = 1.5e14;
t.b = 2.75e11;
t.c = 0.0;
@@ -382,12 +370,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.a = 1.5e22;
t.b = 2.75e11;
t.c = 17.17;
@@ -448,12 +433,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.a = 1.5e4;
t.b = 2.75e8;
t.i = 12345678;
@@ -521,23 +503,30 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.ui = 0x11223344;
t.si = 0x99aabbcc;
Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
USE(dummy);
CHECK_EQ(0x11223344, t.r1);
+#if __BYTE_ORDER == __LITTLE_ENDIAN
CHECK_EQ(0x3344, t.r2);
CHECK_EQ(0xffffbbcc, t.r3);
CHECK_EQ(0x0000bbcc, t.r4);
CHECK_EQ(0xffffffcc, t.r5);
CHECK_EQ(0x3333bbcc, t.r6);
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ CHECK_EQ(0x1122, t.r2);
+ CHECK_EQ(0xffff99aa, t.r3);
+ CHECK_EQ(0x000099aa, t.r4);
+ CHECK_EQ(0xffffff99, t.r5);
+ CHECK_EQ(0x99aa3333, t.r6);
+#else
+#error Unknown endianness
+#endif
}
@@ -598,12 +587,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.a = 1.5e14;
t.b = 2.75e11;
t.c = 2.0;
@@ -697,12 +683,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.input = 0x12345678;
Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0);
USE(dummy);
@@ -745,11 +728,8 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
}
@@ -799,12 +779,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.a = 2.147483646e+09; // 0x7FFFFFFE -> 0xFF80000041DFFFFF as double.
t.b_word = 0x0ff00ff0; // 0x0FF00FF0 -> 0x as double.
Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
@@ -930,18 +907,16 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.reg_init = 0xaabbccdd;
t.mem_init = 0x11223344;
Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
USE(dummy);
+#if __BYTE_ORDER == __LITTLE_ENDIAN
CHECK_EQ(0x44bbccdd, t.lwl_0);
CHECK_EQ(0x3344ccdd, t.lwl_1);
CHECK_EQ(0x223344dd, t.lwl_2);
@@ -961,6 +936,29 @@
CHECK_EQ(0xbbccdd44, t.swr_1);
CHECK_EQ(0xccdd3344, t.swr_2);
CHECK_EQ(0xdd223344, t.swr_3);
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ CHECK_EQ(0x11223344, t.lwl_0);
+ CHECK_EQ(0x223344dd, t.lwl_1);
+ CHECK_EQ(0x3344ccdd, t.lwl_2);
+ CHECK_EQ(0x44bbccdd, t.lwl_3);
+
+ CHECK_EQ(0xaabbcc11, t.lwr_0);
+ CHECK_EQ(0xaabb1122, t.lwr_1);
+ CHECK_EQ(0xaa112233, t.lwr_2);
+ CHECK_EQ(0x11223344, t.lwr_3);
+
+ CHECK_EQ(0xaabbccdd, t.swl_0);
+ CHECK_EQ(0x11aabbcc, t.swl_1);
+ CHECK_EQ(0x1122aabb, t.swl_2);
+ CHECK_EQ(0x112233aa, t.swl_3);
+
+ CHECK_EQ(0xdd223344, t.swr_0);
+ CHECK_EQ(0xccdd3344, t.swr_1);
+ CHECK_EQ(0xbbccdd44, t.swr_2);
+ CHECK_EQ(0xaabbccdd, t.swr_3);
+#else
+#error Unknown endianness
+#endif
}
@@ -1035,12 +1033,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.x = 1;
t.y = 2;
t.y1 = 3;
@@ -1092,12 +1087,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.cvt_big_in = 0xFFFFFFFF;
t.cvt_small_in = 333;
@@ -1213,12 +1205,9 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
t.round_up_in = 123.51;
t.round_down_in = 123.49;
diff --git a/test/cctest/test-assembler-x64.cc b/test/cctest/test-assembler-x64.cc
index eddc107..eb9fee8 100644
--- a/test/cctest/test-assembler-x64.cc
+++ b/test/cctest/test-assembler-x64.cc
@@ -575,11 +575,8 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F0 f = FUNCTION_CAST<F0>(code->entry());
int res = f();
@@ -627,11 +624,8 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F0 f = FUNCTION_CAST<F0>(code->entry());
int res = f();
@@ -692,16 +686,13 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
+ code->Print();
#endif
- F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ F3 f = FUNCTION_CAST<F3>(code->entry());
uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
CHECK_EQ(0x12345678, f(uint64_to_double(value1)));
uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
@@ -731,16 +722,15 @@
CodeDesc desc;
assm.GetCode(&desc);
- Code* code = Code::cast(isolate->heap()->CreateCode(
+ Handle<Code> code = isolate->factory()->NewCode(
desc,
Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked());
- CHECK(code->IsCode());
+ Handle<Code>());
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
+ code->Print();
#endif
- F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
+ F6 f = FUNCTION_CAST<F6>(code->entry());
CHECK_EQ(2, f(1.0, 2.0));
}
#undef __
diff --git a/test/cctest/test-compiler.cc b/test/cctest/test-compiler.cc
index 3df2dfd..cc9258a 100644
--- a/test/cctest/test-compiler.cc
+++ b/test/cctest/test-compiler.cc
@@ -38,10 +38,8 @@
static Handle<Object> GetGlobalProperty(const char* name) {
Isolate* isolate = CcTest::i_isolate();
- Handle<String> internalized_name =
- isolate->factory()->InternalizeUtf8String(name);
return Object::GetProperty(
- isolate->global_object(), internalized_name).ToHandleChecked();
+ isolate, isolate->global_object(), name).ToHandleChecked();
}
@@ -58,8 +56,8 @@
static Handle<JSFunction> Compile(const char* source) {
Isolate* isolate = CcTest::i_isolate();
- Handle<String> source_code(
- isolate->factory()->NewStringFromUtf8(CStrVector(source)));
+ Handle<String> source_code = isolate->factory()->NewStringFromUtf8(
+ CStrVector(source)).ToHandleChecked();
Handle<SharedFunctionInfo> shared_function =
Compiler::CompileScript(source_code,
Handle<String>(),
@@ -259,9 +257,9 @@
Handle<Script> script = factory->NewScript(factory->empty_string());
script->set_source(CcTest::heap()->undefined_value());
- CHECK_EQ(-1, GetScriptLineNumber(script, 0));
- CHECK_EQ(-1, GetScriptLineNumber(script, 100));
- CHECK_EQ(-1, GetScriptLineNumber(script, -1));
+ CHECK_EQ(-1, Script::GetLineNumber(script, 0));
+ CHECK_EQ(-1, Script::GetLineNumber(script, 100));
+ CHECK_EQ(-1, Script::GetLineNumber(script, -1));
}
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 9bcefa4..d3fcf7d 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -148,8 +148,7 @@
// Enqueue code creation events.
const char* aaa_str = "aaa";
- i::Handle<i::String> aaa_name = factory->NewStringFromAscii(
- i::Vector<const char>(aaa_str, i::StrLength(aaa_str)));
+ i::Handle<i::String> aaa_name = factory->NewStringFromAsciiChecked(aaa_str);
profiler.CodeCreateEvent(i::Logger::FUNCTION_TAG, aaa_code, *aaa_name);
profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment_code, "comment");
profiler.CodeCreateEvent(i::Logger::STUB_TAG, args5_code, 5);
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index b66416f..7bb60b7 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -7510,7 +7510,7 @@
OS::SNPrintF(script_vector, "%%GetFrameDetails(%d, %d)[5]", break_id, i);
v8::Local<v8::Value> result = CompileRun(script);
CHECK_EQ(expected_line_number[i],
- i::GetScriptLineNumber(source_script, result->Int32Value()));
+ i::Script::GetLineNumber(source_script, result->Int32Value()));
}
v8::Debug::SetDebugEventListener2(NULL);
v8::V8::TerminateExecution(CcTest::isolate());
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index 7ca95f6..55408b7 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -462,15 +462,13 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ USE(code);
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
- byte* begin = Code::cast(code)->instruction_start();
- byte* end = begin + Code::cast(code)->instruction_size();
+ code->Print();
+ byte* begin = code->instruction_start();
+ byte* end = begin + code->instruction_size();
disasm::Disassembler::Disassemble(stdout, begin, end);
#endif
}
diff --git a/test/cctest/test-disasm-x64.cc b/test/cctest/test-disasm-x64.cc
index 52f4e17..57fdbfb 100644
--- a/test/cctest/test-disasm-x64.cc
+++ b/test/cctest/test-disasm-x64.cc
@@ -431,15 +431,13 @@
CodeDesc desc;
assm.GetCode(&desc);
- Object* code = CcTest::heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ USE(code);
#ifdef OBJECT_PRINT
- Code::cast(code)->Print();
- byte* begin = Code::cast(code)->instruction_start();
- byte* end = begin + Code::cast(code)->instruction_size();
+ code->Print();
+ byte* begin = code->instruction_start();
+ byte* end = begin + code->instruction_size();
disasm::Disassembler::Disassemble(stdout, begin, end);
#endif
}
diff --git a/test/cctest/test-func-name-inference.cc b/test/cctest/test-func-name-inference.cc
index d7c5083..f426905 100644
--- a/test/cctest/test-func-name-inference.cc
+++ b/test/cctest/test-func-name-inference.cc
@@ -70,7 +70,7 @@
// Find the position of a given func source substring in the source.
Handle<String> func_pos_str =
- factory->NewStringFromAscii(CStrVector(func_pos_src));
+ factory->NewStringFromAsciiChecked(func_pos_src);
int func_pos = Runtime::StringMatch(isolate,
script_src,
func_pos_str,
diff --git a/test/cctest/test-global-handles.cc b/test/cctest/test-global-handles.cc
index 48b6655..1ab90ec 100644
--- a/test/cctest/test-global-handles.cc
+++ b/test/cctest/test-global-handles.cc
@@ -86,19 +86,19 @@
TEST(IterateObjectGroupsOldApi) {
CcTest::InitializeVM();
- GlobalHandles* global_handles = CcTest::i_isolate()->global_handles();
- Heap* heap = CcTest::heap();
+ Isolate* isolate = CcTest::i_isolate();
+ GlobalHandles* global_handles = isolate->global_handles();
v8::HandleScope handle_scope(CcTest::isolate());
Handle<Object> g1s1 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g1s2 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g2s1 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g2s2 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
TestRetainedObjectInfo info1;
TestRetainedObjectInfo info2;
@@ -181,20 +181,20 @@
TEST(IterateObjectGroups) {
CcTest::InitializeVM();
- GlobalHandles* global_handles = CcTest::i_isolate()->global_handles();
- Heap* heap = CcTest::heap();
+ Isolate* isolate = CcTest::i_isolate();
+ GlobalHandles* global_handles = isolate->global_handles();
v8::HandleScope handle_scope(CcTest::isolate());
Handle<Object> g1s1 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g1s2 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g2s1 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g2s2 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
TestRetainedObjectInfo info1;
TestRetainedObjectInfo info2;
@@ -276,25 +276,25 @@
TEST(ImplicitReferences) {
CcTest::InitializeVM();
- GlobalHandles* global_handles = CcTest::i_isolate()->global_handles();
- Heap* heap = CcTest::heap();
+ Isolate* isolate = CcTest::i_isolate();
+ GlobalHandles* global_handles = isolate->global_handles();
v8::HandleScope handle_scope(CcTest::isolate());
Handle<Object> g1s1 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g1c1 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g1c2 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g2s1 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g2s2 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
Handle<Object> g2c1 =
- global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
+ global_handles->Create(*isolate->factory()->NewFixedArray(1));
global_handles->SetObjectGroupId(g1s1.location(), UniqueId(1));
global_handles->SetObjectGroupId(g2s1.location(), UniqueId(2));
diff --git a/test/cctest/test-hashing.cc b/test/cctest/test-hashing.cc
index 66ee041..9a7d61d 100644
--- a/test/cctest/test-hashing.cc
+++ b/test/cctest/test-hashing.cc
@@ -203,7 +203,8 @@
CHECK(code->IsCode());
HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry());
- Handle<String> v8_string = factory->NewStringFromOneByte(string);
+ Handle<String> v8_string =
+ factory->NewStringFromOneByte(string).ToHandleChecked();
v8_string->set_hash_field(String::kEmptyHashField);
#ifdef USE_SIMULATOR
uint32_t codegen_hash = static_cast<uint32_t>(
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index c38af93..a57da7f 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -441,10 +441,8 @@
CHECK_EQ(1, global->InternalFieldCount());
i::Factory* factory = CcTest::i_isolate()->factory();
- i::Handle<i::String> first =
- factory->NewStringFromAscii(i::CStrVector("0123456789"));
- i::Handle<i::String> second =
- factory->NewStringFromAscii(i::CStrVector("0123456789"));
+ i::Handle<i::String> first = factory->NewStringFromStaticAscii("0123456789");
+ i::Handle<i::String> second = factory->NewStringFromStaticAscii("0123456789");
i::Handle<i::String> cons_string =
factory->NewConsString(first, second).ToHandleChecked();
@@ -2488,8 +2486,7 @@
v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
i::Factory* factory = CcTest::i_isolate()->factory();
- i::Handle<i::String> string =
- factory->NewStringFromAscii(i::CStrVector("string"));
+ i::Handle<i::String> string = factory->NewStringFromStaticAscii("string");
i::Handle<i::Object> box = factory->NewBox(string);
global->Set(0, v8::ToApiHandle<v8::Object>(box));
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index eec5264..c0cc7e6 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -99,12 +99,11 @@
static void CheckNumber(Isolate* isolate, double value, const char* string) {
- Object* obj = CcTest::heap()->NumberFromDouble(value)->ToObjectChecked();
- CHECK(obj->IsNumber());
- Handle<Object> handle(obj, isolate);
- Object* print_string =
- *Execution::ToString(isolate, handle).ToHandleChecked();
- CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string)));
+ Handle<Object> number = isolate->factory()->NewNumber(value);
+ CHECK(number->IsNumber());
+ Handle<Object> print_string =
+ Execution::ToString(isolate, number).ToHandleChecked();
+ CHECK(String::cast(*print_string)->IsUtf8EqualTo(CStrVector(string)));
}
@@ -118,30 +117,24 @@
CodeDesc desc;
assm.GetCode(&desc);
- Heap* heap = isolate->heap();
- Object* code = heap->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
CHECK(code->IsCode());
- HeapObject* obj = HeapObject::cast(code);
+ HeapObject* obj = HeapObject::cast(*code);
Address obj_addr = obj->address();
for (int i = 0; i < obj->Size(); i += kPointerSize) {
Object* found = isolate->FindCodeObject(obj_addr + i);
- CHECK_EQ(code, found);
+ CHECK_EQ(*code, found);
}
- Object* copy = heap->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(copy->IsCode());
- HeapObject* obj_copy = HeapObject::cast(copy);
+ Handle<Code> copy = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ HeapObject* obj_copy = HeapObject::cast(*copy);
Object* not_right = isolate->FindCodeObject(obj_copy->address() +
obj_copy->Size() / 2);
- CHECK(not_right != code);
+ CHECK(not_right != *code);
}
@@ -162,59 +155,56 @@
Heap* heap = isolate->heap();
HandleScope sc(isolate);
- Object* value = heap->NumberFromDouble(1.000123)->ToObjectChecked();
+ Handle<Object> value = factory->NewNumber(1.000123);
CHECK(value->IsHeapNumber());
CHECK(value->IsNumber());
CHECK_EQ(1.000123, value->Number());
- value = heap->NumberFromDouble(1.0)->ToObjectChecked();
+ value = factory->NewNumber(1.0);
CHECK(value->IsSmi());
CHECK(value->IsNumber());
CHECK_EQ(1.0, value->Number());
- value = heap->NumberFromInt32(1024)->ToObjectChecked();
+ value = factory->NewNumberFromInt(1024);
CHECK(value->IsSmi());
CHECK(value->IsNumber());
CHECK_EQ(1024.0, value->Number());
- value = heap->NumberFromInt32(Smi::kMinValue)->ToObjectChecked();
+ value = factory->NewNumberFromInt(Smi::kMinValue);
CHECK(value->IsSmi());
CHECK(value->IsNumber());
- CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
+ CHECK_EQ(Smi::kMinValue, Handle<Smi>::cast(value)->value());
- value = heap->NumberFromInt32(Smi::kMaxValue)->ToObjectChecked();
+ value = factory->NewNumberFromInt(Smi::kMaxValue);
CHECK(value->IsSmi());
CHECK(value->IsNumber());
- CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
+ CHECK_EQ(Smi::kMaxValue, Handle<Smi>::cast(value)->value());
#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM64)
// TODO(lrn): We need a NumberFromIntptr function in order to test this.
- value = heap->NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked();
+ value = factory->NewNumberFromInt(Smi::kMinValue - 1);
CHECK(value->IsHeapNumber());
CHECK(value->IsNumber());
CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
#endif
- MaybeObject* maybe_value =
- heap->NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
- value = maybe_value->ToObjectChecked();
+ value = factory->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
CHECK(value->IsHeapNumber());
CHECK(value->IsNumber());
CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
value->Number());
- maybe_value = heap->NumberFromUint32(static_cast<uint32_t>(1) << 31);
- value = maybe_value->ToObjectChecked();
+ value = factory->NewNumberFromUint(static_cast<uint32_t>(1) << 31);
CHECK(value->IsHeapNumber());
CHECK(value->IsNumber());
CHECK_EQ(static_cast<double>(static_cast<uint32_t>(1) << 31),
value->Number());
// nan oddball checks
- CHECK(heap->nan_value()->IsNumber());
- CHECK(std::isnan(heap->nan_value()->Number()));
+ CHECK(factory->nan_value()->IsNumber());
+ CHECK(std::isnan(factory->nan_value()->Number()));
- Handle<String> s = factory->NewStringFromAscii(CStrVector("fisk hest "));
+ Handle<String> s = factory->NewStringFromStaticAscii("fisk hest ");
CHECK(s->IsString());
CHECK_EQ(10, s->length());
@@ -277,8 +267,8 @@
{
HandleScope inner_scope(isolate);
// Allocate a function and keep it in global object's property.
- Handle<JSFunction> function =
- factory->NewFunction(name, factory->undefined_value());
+ Handle<JSFunction> function = factory->NewFunctionWithPrototype(
+ name, factory->undefined_value());
Handle<Map> initial_map =
factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
function->set_initial_map(*initial_map);
@@ -329,7 +319,8 @@
static void VerifyStringAllocation(Isolate* isolate, const char* string) {
HandleScope scope(isolate);
- Handle<String> s = isolate->factory()->NewStringFromUtf8(CStrVector(string));
+ Handle<String> s = isolate->factory()->NewStringFromUtf8(
+ CStrVector(string)).ToHandleChecked();
CHECK_EQ(StrLength(string), s->length());
for (int index = 0; index < s->length(); index++) {
CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));
@@ -356,7 +347,7 @@
v8::HandleScope scope(CcTest::isolate());
const char* name = "Kasper the spunky";
- Handle<String> string = factory->NewStringFromAscii(CStrVector(name));
+ Handle<String> string = factory->NewStringFromAsciiChecked(name);
CHECK_EQ(StrLength(name), string->length());
}
@@ -376,7 +367,7 @@
{
HandleScope scope(isolate);
- Handle<Object> i = factory->NewStringFromAscii(CStrVector("fisk"));
+ Handle<Object> i = factory->NewStringFromStaticAscii("fisk");
Handle<Object> u = factory->NewNumber(1.12344);
h1 = global_handles->Create(*i);
@@ -431,7 +422,7 @@
{
HandleScope scope(isolate);
- Handle<Object> i = factory->NewStringFromAscii(CStrVector("fisk"));
+ Handle<Object> i = factory->NewStringFromStaticAscii("fisk");
Handle<Object> u = factory->NewNumber(1.12344);
h1 = global_handles->Create(*i);
@@ -473,7 +464,7 @@
{
HandleScope scope(isolate);
- Handle<Object> i = factory->NewStringFromAscii(CStrVector("fisk"));
+ Handle<Object> i = factory->NewStringFromStaticAscii("fisk");
Handle<Object> u = factory->NewNumber(1.12344);
h1 = global_handles->Create(*i);
@@ -519,7 +510,7 @@
{
HandleScope scope(isolate);
- Handle<Object> i = factory->NewStringFromAscii(CStrVector("fisk"));
+ Handle<Object> i = factory->NewStringFromStaticAscii("fisk");
h = global_handles->Create(*i);
}
@@ -635,8 +626,8 @@
v8::HandleScope sc(CcTest::isolate());
Handle<String> name = factory->InternalizeUtf8String("theFunction");
- Handle<JSFunction> function =
- factory->NewFunction(name, factory->undefined_value());
+ Handle<JSFunction> function = factory->NewFunctionWithPrototype(
+ name, factory->undefined_value());
Handle<Map> initial_map =
factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
function->set_initial_map(*initial_map);
@@ -713,7 +704,7 @@
// check string and internalized string match
const char* string1 = "fisk";
- Handle<String> s1 = factory->NewStringFromAscii(CStrVector(string1));
+ 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));
@@ -722,7 +713,7 @@
const char* string2 = "fugl";
Handle<String> s2_string = factory->InternalizeUtf8String(string2);
JSReceiver::SetProperty(obj, s2_string, one, NONE, SLOPPY).Check();
- Handle<String> s2 = factory->NewStringFromAscii(CStrVector(string2));
+ Handle<String> s2 = factory->NewStringFromAsciiChecked(string2);
CHECK(JSReceiver::HasLocalProperty(obj, s2));
}
@@ -734,8 +725,8 @@
v8::HandleScope sc(CcTest::isolate());
Handle<String> name = factory->InternalizeUtf8String("theFunction");
- Handle<JSFunction> function =
- factory->NewFunction(name, factory->undefined_value());
+ Handle<JSFunction> function = factory->NewFunctionWithPrototype(
+ name, factory->undefined_value());
Handle<Map> initial_map =
factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
function->set_initial_map(*initial_map);
@@ -766,6 +757,7 @@
Handle<JSFunction> function = Handle<JSFunction>::cast(fun_obj);
// Allocate the object.
+ Handle<Object> element;
Handle<JSObject> object = factory->NewJSObject(function);
Handle<JSArray> array = Handle<JSArray>::cast(object);
// We just initialized the VM, no heap allocation failure yet.
@@ -780,7 +772,8 @@
// array[length] = name.
JSReceiver::SetElement(array, 0, name, NONE, SLOPPY).Check();
CHECK_EQ(Smi::FromInt(1), array->length());
- CHECK_EQ(*i::Object::GetElement(isolate, array, 0).ToHandleChecked(), *name);
+ element = i::Object::GetElement(isolate, array, 0).ToHandleChecked();
+ CHECK_EQ(*element, *name);
// Set array length with larger than smi value.
Handle<Object> length =
@@ -797,9 +790,10 @@
uint32_t new_int_length = 0;
CHECK(array->length()->ToArrayIndex(&new_int_length));
CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
- CHECK_EQ(*i::Object::GetElement(isolate, array, int_length).ToHandleChecked(),
- *name);
- CHECK_EQ(*i::Object::GetElement(isolate, array, 0).ToHandleChecked(), *name);
+ element = Object::GetElement(isolate, array, int_length).ToHandleChecked();
+ CHECK_EQ(*element, *name);
+ element = Object::GetElement(isolate, array, 0).ToHandleChecked();
+ CHECK_EQ(*element, *name);
}
@@ -827,18 +821,23 @@
JSReceiver::SetElement(obj, 1, second, NONE, SLOPPY).Check();
// Make the clone.
+ Handle<Object> value1, value2;
Handle<JSObject> clone = JSObject::Copy(obj);
CHECK(!clone.is_identical_to(obj));
- CHECK_EQ(*i::Object::GetElement(isolate, obj, 0).ToHandleChecked(),
- *i::Object::GetElement(isolate, clone, 0).ToHandleChecked());
- CHECK_EQ(*i::Object::GetElement(isolate, obj, 1).ToHandleChecked(),
- *i::Object::GetElement(isolate, clone, 1).ToHandleChecked());
+ value1 = Object::GetElement(isolate, obj, 0).ToHandleChecked();
+ value2 = Object::GetElement(isolate, clone, 0).ToHandleChecked();
+ CHECK_EQ(*value1, *value2);
+ value1 = Object::GetElement(isolate, obj, 1).ToHandleChecked();
+ value2 = Object::GetElement(isolate, clone, 1).ToHandleChecked();
+ CHECK_EQ(*value1, *value2);
- CHECK_EQ(*Object::GetProperty(obj, first).ToHandleChecked(),
- *Object::GetProperty(clone, first).ToHandleChecked());
- CHECK_EQ(*Object::GetProperty(obj, second).ToHandleChecked(),
- *Object::GetProperty(clone, second).ToHandleChecked());
+ value1 = Object::GetProperty(obj, first).ToHandleChecked();
+ value2 = Object::GetProperty(clone, first).ToHandleChecked();
+ CHECK_EQ(*value1, *value2);
+ value1 = Object::GetProperty(obj, second).ToHandleChecked();
+ value2 = Object::GetProperty(clone, second).ToHandleChecked();
+ CHECK_EQ(*value1, *value2);
// Flip the values.
JSReceiver::SetProperty(clone, first, two, NONE, SLOPPY).Check();
@@ -847,15 +846,19 @@
JSReceiver::SetElement(clone, 0, second, NONE, SLOPPY).Check();
JSReceiver::SetElement(clone, 1, first, NONE, SLOPPY).Check();
- CHECK_EQ(*i::Object::GetElement(isolate, obj, 1).ToHandleChecked(),
- *i::Object::GetElement(isolate, clone, 0).ToHandleChecked());
- CHECK_EQ(*i::Object::GetElement(isolate, obj, 0).ToHandleChecked(),
- *i::Object::GetElement(isolate, clone, 1).ToHandleChecked());
+ value1 = Object::GetElement(isolate, obj, 1).ToHandleChecked();
+ value2 = Object::GetElement(isolate, clone, 0).ToHandleChecked();
+ CHECK_EQ(*value1, *value2);
+ value1 = Object::GetElement(isolate, obj, 0).ToHandleChecked();
+ value2 = Object::GetElement(isolate, clone, 1).ToHandleChecked();
+ CHECK_EQ(*value1, *value2);
- CHECK_EQ(*Object::GetProperty(obj, second).ToHandleChecked(),
- *Object::GetProperty(clone, first).ToHandleChecked());
- CHECK_EQ(*Object::GetProperty(obj, first).ToHandleChecked(),
- *Object::GetProperty(clone, second).ToHandleChecked());
+ value1 = Object::GetProperty(obj, second).ToHandleChecked();
+ value2 = Object::GetProperty(clone, first).ToHandleChecked();
+ CHECK_EQ(*value1, *value2);
+ value1 = Object::GetProperty(obj, first).ToHandleChecked();
+ value2 = Object::GetProperty(clone, second).ToHandleChecked();
+ CHECK_EQ(*value1, *value2);
}
@@ -884,12 +887,12 @@
Handle<String> ascii_sym =
factory->InternalizeOneByteString(OneByteVector(ascii, length));
CHECK_EQ(length, ascii_sym->length());
- Handle<String> non_ascii_str =
- factory->NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
+ Handle<String> non_ascii_str = factory->NewStringFromUtf8(
+ Vector<const char>(non_ascii, 3 * length)).ToHandleChecked();
non_ascii_str->Hash();
CHECK_EQ(length, non_ascii_str->length());
- Handle<String> ascii_str =
- factory->NewStringFromUtf8(Vector<const char>(ascii, length));
+ Handle<String> ascii_str = factory->NewStringFromUtf8(
+ Vector<const char>(ascii, length)).ToHandleChecked();
ascii_str->Hash();
CHECK_EQ(length, ascii_str->length());
DeleteArray(non_ascii);
@@ -933,17 +936,16 @@
// Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
objs[next_objs_index++] =
- factory->NewStringFromAscii(CStrVector("abcdefghij"));
+ factory->NewStringFromStaticAscii("abcdefghij");
objs[next_objs_index++] =
- factory->NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
+ factory->NewStringFromStaticAscii("abcdefghij", TENURED);
// Allocate a large string (for large object space).
int large_size = Page::kMaxRegularHeapObjectSize + 1;
char* str = new char[large_size];
for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
str[large_size - 1] = '\0';
- objs[next_objs_index++] =
- factory->NewStringFromAscii(CStrVector(str), TENURED);
+ objs[next_objs_index++] = factory->NewStringFromAsciiChecked(str, TENURED);
delete[] str;
// Add a Map object to look for.
@@ -2637,14 +2639,15 @@
v8::HandleScope scope(CcTest::isolate());
static const int transitions_count = 256;
+ CompileRun("function F() {}");
{
AlwaysAllocateScope always_allocate(CcTest::i_isolate());
for (int i = 0; i < transitions_count; i++) {
EmbeddedVector<char, 64> buffer;
- OS::SNPrintF(buffer, "var o = new Object; o.prop%d = %d;", i, i);
+ OS::SNPrintF(buffer, "var o = new F; o.prop%d = %d;", i, i);
CompileRun(buffer.start());
}
- CompileRun("var root = new Object;");
+ CompileRun("var root = new F;");
}
Handle<JSObject> root =
@@ -2673,7 +2676,7 @@
AlwaysAllocateScope always_allocate(CcTest::i_isolate());
for (int i = 0; i < transitions_count; i++) {
EmbeddedVector<char, 64> buffer;
- OS::SNPrintF(buffer, "var o = new Object; o.prop%d = %d;", i, i);
+ OS::SNPrintF(buffer, "var o = new F; o.prop%d = %d;", i, i);
CompileRun(buffer.start());
}
}
@@ -2706,8 +2709,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
static const int transitions_count = 10;
+ CompileRun("function F() { }");
AddTransitions(transitions_count);
- CompileRun("var root = new Object;");
+ CompileRun("var root = new F;");
Handle<JSObject> root = GetByName("root");
// Count number of live transitions before marking.
@@ -2715,8 +2719,8 @@
CHECK_EQ(transitions_count, transitions_before);
// Get rid of o
- CompileRun("o = new Object;"
- "root = new Object");
+ CompileRun("o = new F;"
+ "root = new F");
root = GetByName("root");
AddPropertyTo(2, root, "funny");
@@ -2734,8 +2738,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
static const int transitions_count = 10;
+ CompileRun("function F() {}");
AddTransitions(transitions_count);
- CompileRun("var root = new Object;");
+ CompileRun("var root = new F;");
Handle<JSObject> root = GetByName("root");
// Count number of live transitions before marking.
@@ -2759,8 +2764,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
static const int transitions_count = 10;
+ CompileRun("function F() {}");
AddTransitions(transitions_count);
- CompileRun("var root = new Object;");
+ CompileRun("var root = new F;");
Handle<JSObject> root = GetByName("root");
// Count number of live transitions before marking.
@@ -2784,16 +2790,17 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
static const int transitions_count = 1;
+ CompileRun("function F() {}");
AddTransitions(transitions_count);
- CompileRun("var root = new Object;");
+ CompileRun("var root = new F;");
Handle<JSObject> root = GetByName("root");
// Count number of live transitions before marking.
int transitions_before = CountMapTransitions(root->map());
CHECK_EQ(transitions_count, transitions_before);
- CompileRun("o = new Object;"
- "root = new Object");
+ CompileRun("o = new F;"
+ "root = new F");
root = GetByName("root");
ASSERT(root->map()->transitions()->IsSimpleTransition());
AddPropertyTo(2, root, "happy");
@@ -2950,7 +2957,7 @@
// Generate a parent that lives in new-space.
v8::HandleScope inner_scope(CcTest::isolate());
const char* c = "This text is long enough to trigger sliced strings.";
- Handle<String> s = factory->NewStringFromAscii(CStrVector(c));
+ Handle<String> s = factory->NewStringFromAsciiChecked(c);
CHECK(s->IsSeqOneByteString());
CHECK(CcTest::heap()->InNewSpace(*s));
@@ -3535,8 +3542,8 @@
// We need filler the size of AllocationMemento object, plus an extra
// fill pointer value.
- MaybeObject* maybe_object = CcTest::heap()->AllocateRaw(
- AllocationMemento::kSize + kPointerSize, NEW_SPACE, OLD_POINTER_SPACE);
+ MaybeObject* maybe_object = CcTest::heap()->new_space()->AllocateRaw(
+ AllocationMemento::kSize + kPointerSize);
Object* obj = NULL;
CHECK(maybe_object->ToObject(&obj));
Address addr_obj = reinterpret_cast<Address>(
diff --git a/test/cctest/test-macro-assembler-arm.cc b/test/cctest/test-macro-assembler-arm.cc
index d40b8a5..8aed4c2 100644
--- a/test/cctest/test-macro-assembler-arm.cc
+++ b/test/cctest/test-macro-assembler-arm.cc
@@ -91,13 +91,10 @@
CodeDesc desc;
masm->GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
- F f = FUNCTION_CAST<F>(Code::cast(code)->entry());
+ F f = FUNCTION_CAST<F>(code->entry());
// Initialise source data with non-zero bytes.
for (int i = 0; i < data_size; i++) {
@@ -218,14 +215,11 @@
CodeDesc desc;
masm->GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
// Call the function from C++.
- F5 f = FUNCTION_CAST<F5>(Code::cast(code)->entry());
+ F5 f = FUNCTION_CAST<F5>(code->entry());
CHECK_EQ(0, CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
}
diff --git a/test/cctest/test-macro-assembler-mips.cc b/test/cctest/test-macro-assembler-mips.cc
index 3154aac..a5045a8 100644
--- a/test/cctest/test-macro-assembler-mips.cc
+++ b/test/cctest/test-macro-assembler-mips.cc
@@ -91,13 +91,10 @@
CodeDesc desc;
masm->GetCode(&desc);
- Object* code = isolate->heap()->CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Code>())->ToObjectChecked();
- CHECK(code->IsCode());
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
- ::F f = FUNCTION_CAST< ::F>(Code::cast(code)->entry());
+ ::F f = FUNCTION_CAST< ::F>(code->entry());
// Initialise source data with non-zero bytes.
for (int i = 0; i < data_size; i++) {
diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc
index b08f5d4..586b948 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -39,6 +39,7 @@
#include "v8.h"
+#include "full-codegen.h"
#include "global-handles.h"
#include "snapshot.h"
#include "cctest.h"
@@ -158,7 +159,7 @@
{ HandleScope scope(isolate);
// allocate a garbage
Handle<String> func_name = factory->InternalizeUtf8String("theFunction");
- Handle<JSFunction> function = factory->NewFunction(
+ Handle<JSFunction> function = factory->NewFunctionWithPrototype(
func_name, factory->undefined_value());
Handle<Map> initial_map = factory->NewMap(
JS_OBJECT_TYPE, JSObject::kHeaderSize);
@@ -496,18 +497,12 @@
CcTest::InitializeVM();
intptr_t delta = MemoryInUse() - initial_memory;
printf("delta: %" V8_PTR_PREFIX "d kB\n", delta / 1024);
- if (sizeof(initial_memory) == 8) { // 64-bit.
- if (v8::internal::Snapshot::IsEnabled()) {
- CHECK_LE(delta, 4100 * 1024);
- } else {
- CHECK_LE(delta, 4600 * 1024);
- }
- } else { // 32-bit.
- if (v8::internal::Snapshot::IsEnabled()) {
- CHECK_LE(delta, 3100 * 1024);
- } else {
- CHECK_LE(delta, 3450 * 1024);
- }
+ if (v8::internal::Snapshot::IsEnabled()) {
+ CHECK_LE(delta,
+ 3200 * 1024 * FullCodeGenerator::kBootCodeSizeMultiplier / 100);
+ } else {
+ CHECK_LE(delta,
+ 3350 * 1024 * FullCodeGenerator::kBootCodeSizeMultiplier / 100);
}
}
}
diff --git a/test/cctest/test-object-observe.cc b/test/cctest/test-object-observe.cc
index 188d222..a8cbaf6 100644
--- a/test/cctest/test-object-observe.cc
+++ b/test/cctest/test-object-observe.cc
@@ -407,20 +407,19 @@
"Object.observe(obj, function(){});"
"Object.getNotifier(obj);"
"obj = null;");
- i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(CcTest::isolate());
+ i::Isolate* i_isolate = CcTest::i_isolate();
i::Handle<i::JSObject> observation_state =
i_isolate->factory()->observation_state();
i::Handle<i::JSWeakMap> callbackInfoMap =
- i::Handle<i::JSWeakMap>::cast(
- i::GetProperty(
- observation_state, "callbackInfoMap").ToHandleChecked());
+ i::Handle<i::JSWeakMap>::cast(i::Object::GetProperty(
+ i_isolate, observation_state, "callbackInfoMap").ToHandleChecked());
i::Handle<i::JSWeakMap> objectInfoMap =
- i::Handle<i::JSWeakMap>::cast(
- i::GetProperty(observation_state, "objectInfoMap").ToHandleChecked());
+ i::Handle<i::JSWeakMap>::cast(i::Object::GetProperty(
+ i_isolate, observation_state, "objectInfoMap").ToHandleChecked());
i::Handle<i::JSWeakMap> notifierObjectInfoMap =
- i::Handle<i::JSWeakMap>::cast(
- i::GetProperty(
- observation_state, "notifierObjectInfoMap").ToHandleChecked());
+ i::Handle<i::JSWeakMap>::cast(i::Object::GetProperty(
+ i_isolate, observation_state, "notifierObjectInfoMap")
+ .ToHandleChecked());
CHECK_EQ(1, NumberOfElements(callbackInfoMap));
CHECK_EQ(1, NumberOfElements(objectInfoMap));
CHECK_EQ(1, NumberOfElements(notifierObjectInfoMap));
diff --git a/test/cctest/test-ordered-hash-table.cc b/test/cctest/test-ordered-hash-table.cc
index f6ebc16..b7c043d 100644
--- a/test/cctest/test-ordered-hash-table.cc
+++ b/test/cctest/test-ordered-hash-table.cc
@@ -36,7 +36,25 @@
using namespace v8::internal;
+
+void CheckIterResultObject(Isolate* isolate,
+ Handle<JSObject> result,
+ Handle<Object> value,
+ bool done) {
+ Handle<Object> value_object =
+ Object::GetProperty(isolate, result, "value").ToHandleChecked();
+ Handle<Object> done_object =
+ Object::GetProperty(isolate, result, "done").ToHandleChecked();
+
+ CHECK_EQ(*value_object, *value);
+ CHECK(done_object->IsBoolean());
+ CHECK_EQ(done_object->BooleanValue(), done);
+}
+
+
TEST(Set) {
+ i::FLAG_harmony_collections = true;
+
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
@@ -46,6 +64,11 @@
CHECK_EQ(0, ordered_set->NumberOfElements());
CHECK_EQ(0, ordered_set->NumberOfDeletedElements());
+ Handle<JSSetIterator> value_iterator =
+ JSSetIterator::Create(ordered_set, JSSetIterator::kKindValues);
+ Handle<JSSetIterator> value_iterator_2 =
+ JSSetIterator::Create(ordered_set, JSSetIterator::kKindValues);
+
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
CHECK(!ordered_set->Contains(*obj));
@@ -68,6 +91,18 @@
CHECK(ordered_set->Contains(*obj2));
CHECK(ordered_set->Contains(*obj3));
+ // Test iteration
+ CheckIterResultObject(
+ isolate, JSSetIterator::Next(value_iterator), obj1, false);
+ CheckIterResultObject(
+ isolate, JSSetIterator::Next(value_iterator), obj2, false);
+ CheckIterResultObject(
+ isolate, JSSetIterator::Next(value_iterator), obj3, false);
+ CheckIterResultObject(isolate,
+ JSSetIterator::Next(value_iterator),
+ factory->undefined_value(),
+ true);
+
// Test growth
ordered_set = OrderedHashSet::Add(ordered_set, obj);
Handle<JSObject> obj4 = factory->NewJSObjectFromMap(map);
@@ -81,6 +116,22 @@
CHECK_EQ(0, ordered_set->NumberOfDeletedElements());
CHECK_EQ(4, ordered_set->NumberOfBuckets());
+ // Test iteration after growth
+ CheckIterResultObject(
+ isolate, JSSetIterator::Next(value_iterator_2), obj1, false);
+ CheckIterResultObject(
+ isolate, JSSetIterator::Next(value_iterator_2), obj2, false);
+ CheckIterResultObject(
+ isolate, JSSetIterator::Next(value_iterator_2), obj3, false);
+ CheckIterResultObject(
+ isolate, JSSetIterator::Next(value_iterator_2), obj, false);
+ CheckIterResultObject(
+ isolate, JSSetIterator::Next(value_iterator_2), obj4, false);
+ CheckIterResultObject(isolate,
+ JSSetIterator::Next(value_iterator_2),
+ factory->undefined_value(),
+ true);
+
// Test shrinking
ordered_set = OrderedHashSet::Remove(ordered_set, obj);
ordered_set = OrderedHashSet::Remove(ordered_set, obj1);
@@ -92,6 +143,8 @@
TEST(Map) {
+ i::FLAG_harmony_collections = true;
+
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
@@ -101,6 +154,11 @@
CHECK_EQ(0, ordered_map->NumberOfElements());
CHECK_EQ(0, ordered_map->NumberOfDeletedElements());
+ Handle<JSMapIterator> value_iterator =
+ JSMapIterator::Create(ordered_map, JSMapIterator::kKindValues);
+ Handle<JSMapIterator> key_iterator =
+ JSMapIterator::Create(ordered_map, JSMapIterator::kKindKeys);
+
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
Handle<JSObject> val = factory->NewJSObjectFromMap(map);
@@ -128,6 +186,18 @@
CHECK(ordered_map->Lookup(*obj2)->SameValue(*val2));
CHECK(ordered_map->Lookup(*obj3)->SameValue(*val3));
+ // Test iteration
+ CheckIterResultObject(
+ isolate, JSMapIterator::Next(value_iterator), val1, false);
+ CheckIterResultObject(
+ isolate, JSMapIterator::Next(value_iterator), val2, false);
+ CheckIterResultObject(
+ isolate, JSMapIterator::Next(value_iterator), val3, false);
+ CheckIterResultObject(isolate,
+ JSMapIterator::Next(value_iterator),
+ factory->undefined_value(),
+ true);
+
// Test growth
ordered_map = OrderedHashMap::Put(ordered_map, obj, val);
Handle<JSObject> obj4 = factory->NewJSObjectFromMap(map);
@@ -141,6 +211,22 @@
CHECK_EQ(5, ordered_map->NumberOfElements());
CHECK_EQ(4, ordered_map->NumberOfBuckets());
+ // Test iteration after growth
+ CheckIterResultObject(
+ isolate, JSMapIterator::Next(key_iterator), obj1, false);
+ CheckIterResultObject(
+ isolate, JSMapIterator::Next(key_iterator), obj2, false);
+ CheckIterResultObject(
+ isolate, JSMapIterator::Next(key_iterator), obj3, false);
+ CheckIterResultObject(
+ isolate, JSMapIterator::Next(key_iterator), obj, false);
+ CheckIterResultObject(
+ isolate, JSMapIterator::Next(key_iterator), obj4, false);
+ CheckIterResultObject(isolate,
+ JSMapIterator::Next(key_iterator),
+ factory->undefined_value(),
+ true);
+
// Test shrinking
ordered_map = OrderedHashMap::Put(
ordered_map, obj, factory->the_hole_value());
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index 8b801eb..e0c21f4 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -533,8 +533,7 @@
"var bar = function () { /* second */ }";
v8::HandleScope handles(CcTest::isolate());
- i::Handle<i::String> source(
- factory->NewStringFromAscii(i::CStrVector(program)));
+ i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program);
i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
i::CompleteParserRecorder log;
i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
@@ -630,8 +629,8 @@
uc16_buffer[i] = static_cast<i::uc16>(ascii_source[i]);
}
i::Vector<const char> ascii_vector(ascii_source, static_cast<int>(length));
- i::Handle<i::String> ascii_string(
- factory->NewStringFromAscii(ascii_vector));
+ i::Handle<i::String> ascii_string =
+ factory->NewStringFromAscii(ascii_vector).ToHandleChecked();
TestExternalResource resource(uc16_buffer.get(), length);
i::Handle<i::String> uc16_string(
factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked());
@@ -1209,8 +1208,8 @@
source_data[i].outer_suffix);
// Parse program source.
- i::Handle<i::String> source(
- factory->NewStringFromUtf8(i::CStrVector(program.start())));
+ i::Handle<i::String> source = factory->NewStringFromUtf8(
+ i::CStrVector(program.start())).ToHandleChecked();
CHECK_EQ(source->length(), kProgramSize);
i::Handle<i::Script> script = factory->NewScript(source);
i::CompilationInfoWithZone info(script);
@@ -1254,8 +1253,8 @@
NONE, i::SLOPPY).Check();
}
i::Handle<i::JSObject> builtins(isolate->js_builtins_object());
- i::Handle<i::Object> format_fun =
- i::GetProperty(builtins, "FormatMessage").ToHandleChecked();
+ i::Handle<i::Object> format_fun = i::Object::GetProperty(
+ isolate, builtins, "FormatMessage").ToHandleChecked();
i::Handle<i::Object> arg_handles[] = { format, args_array };
i::Handle<i::Object> result = i::Execution::Call(
isolate, format_fun, builtins, 2, arg_handles).ToHandleChecked();
@@ -1340,8 +1339,8 @@
i::Handle<i::JSObject> exception_handle(
i::JSObject::cast(isolate->pending_exception()));
i::Handle<i::String> message_string =
- i::Handle<i::String>::cast(
- i::GetProperty(exception_handle, "message").ToHandleChecked());
+ i::Handle<i::String>::cast(i::Object::GetProperty(
+ isolate, exception_handle, "message").ToHandleChecked());
if (result == kSuccess) {
i::OS::Print(
@@ -1403,7 +1402,7 @@
size_t flag_list_length,
ParserSyncTestResult result = kSuccessOrError) {
i::Handle<i::String> str =
- CcTest::i_isolate()->factory()->NewStringFromAscii(i::CStrVector(source));
+ CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
for (int bits = 0; bits < (1 << flag_list_length); bits++) {
i::EnumSet<ParserFlag> flags;
for (size_t flag_index = 0; flag_index < flag_list_length; flag_index++) {
@@ -2100,8 +2099,8 @@
for (int i = 0; test_cases[i].program; i++) {
const char* program = test_cases[i].program;
i::Factory* factory = CcTest::i_isolate()->factory();
- i::Handle<i::String> source(
- factory->NewStringFromUtf8(i::CStrVector(program)));
+ i::Handle<i::String> source =
+ factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
i::Handle<i::Script> script = factory->NewScript(source);
i::CompilationInfoWithZone info(script);
i::ScriptData* data = NULL;
diff --git a/test/cctest/test-platform.cc b/test/cctest/test-platform.cc
index b9f8baf..6b28b18 100644
--- a/test/cctest/test-platform.cc
+++ b/test/cctest/test-platform.cc
@@ -59,7 +59,7 @@
do { \
ASM("mov x16, sp; str x16, %0" : "=g" (sp_addr)); \
} while (0)
-#elif defined(__MIPSEL__)
+#elif defined(__MIPSEB__) || defined(__MIPSEL__)
#define GET_STACK_POINTER() \
static int sp_addr = 0; \
do { \
diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index 712fec0..10b227c 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -506,9 +506,9 @@
&compile_data, zone))
return NULL;
Handle<String> pattern = isolate->factory()->
- NewStringFromUtf8(CStrVector(input));
+ NewStringFromUtf8(CStrVector(input)).ToHandleChecked();
Handle<String> sample_subject =
- isolate->factory()->NewStringFromUtf8(CStrVector(""));
+ isolate->factory()->NewStringFromUtf8(CStrVector("")).ToHandleChecked();
RegExpEngine::Compile(&compile_data,
false,
false,
@@ -745,12 +745,12 @@
m.Succeed();
- Handle<String> source = factory->NewStringFromAscii(CStrVector(""));
+ Handle<String> source = factory->NewStringFromStaticAscii("");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
int captures[4] = {42, 37, 87, 117};
- Handle<String> input = factory->NewStringFromAscii(CStrVector("foofoo"));
+ Handle<String> input = factory->NewStringFromStaticAscii("foofoo");
Handle<SeqOneByteString> seq_input = Handle<SeqOneByteString>::cast(input);
const byte* start_adr =
reinterpret_cast<const byte*>(seq_input->GetCharsAddress());
@@ -799,12 +799,12 @@
m.Bind(&fail);
m.Fail();
- Handle<String> source = factory->NewStringFromAscii(CStrVector("^foo"));
+ Handle<String> source = factory->NewStringFromStaticAscii("^foo");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
int captures[4] = {42, 37, 87, 117};
- Handle<String> input = factory->NewStringFromAscii(CStrVector("foofoo"));
+ Handle<String> input = factory->NewStringFromStaticAscii("foofoo");
Handle<SeqOneByteString> seq_input = Handle<SeqOneByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
@@ -822,7 +822,7 @@
CHECK_EQ(-1, captures[2]);
CHECK_EQ(-1, captures[3]);
- input = factory->NewStringFromAscii(CStrVector("barbarbar"));
+ input = factory->NewStringFromStaticAscii("barbarbar");
seq_input = Handle<SeqOneByteString>::cast(input);
start_adr = seq_input->GetCharsAddress();
@@ -865,15 +865,15 @@
m.Bind(&fail);
m.Fail();
- Handle<String> source = factory->NewStringFromAscii(CStrVector("^foo"));
+ Handle<String> source = factory->NewStringFromStaticAscii("^foo");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
int captures[4] = {42, 37, 87, 117};
const uc16 input_data[6] = {'f', 'o', 'o', 'f', 'o',
static_cast<uc16>(0x2603)};
- Handle<String> input =
- factory->NewStringFromTwoByte(Vector<const uc16>(input_data, 6));
+ Handle<String> input = factory->NewStringFromTwoByte(
+ Vector<const uc16>(input_data, 6)).ToHandleChecked();
Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
@@ -893,7 +893,8 @@
const uc16 input_data2[9] = {'b', 'a', 'r', 'b', 'a', 'r', 'b', 'a',
static_cast<uc16>(0x2603)};
- input = factory->NewStringFromTwoByte(Vector<const uc16>(input_data2, 9));
+ input = factory->NewStringFromTwoByte(
+ Vector<const uc16>(input_data2, 9)).ToHandleChecked();
seq_input = Handle<SeqTwoByteString>::cast(input);
start_adr = seq_input->GetCharsAddress();
@@ -928,11 +929,11 @@
m.Bind(&backtrack);
m.Fail();
- Handle<String> source = factory->NewStringFromAscii(CStrVector(".........."));
+ Handle<String> source = factory->NewStringFromStaticAscii("..........");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
- Handle<String> input = factory->NewStringFromAscii(CStrVector("foofoo"));
+ Handle<String> input = factory->NewStringFromStaticAscii("foofoo");
Handle<SeqOneByteString> seq_input = Handle<SeqOneByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
@@ -972,11 +973,11 @@
m.Bind(&missing_match);
m.Fail();
- Handle<String> source = factory->NewStringFromAscii(CStrVector("^(..)..\1"));
+ Handle<String> source = factory->NewStringFromStaticAscii("^(..)..\1");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
- Handle<String> input = factory->NewStringFromAscii(CStrVector("fooofo"));
+ Handle<String> input = factory->NewStringFromStaticAscii("fooofo");
Handle<SeqOneByteString> seq_input = Handle<SeqOneByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
@@ -1021,13 +1022,13 @@
m.Bind(&missing_match);
m.Fail();
- Handle<String> source = factory->NewStringFromAscii(CStrVector("^(..)..\1"));
+ Handle<String> source = factory->NewStringFromStaticAscii("^(..)..\1");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
const uc16 input_data[6] = {'f', 0x2028, 'o', 'o', 'f', 0x2028};
- Handle<String> input =
- factory->NewStringFromTwoByte(Vector<const uc16>(input_data, 6));
+ Handle<String> input = factory->NewStringFromTwoByte(
+ Vector<const uc16>(input_data, 6)).ToHandleChecked();
Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
@@ -1079,11 +1080,11 @@
m.CheckNotCharacter('b', &fail);
m.Succeed();
- Handle<String> source = factory->NewStringFromAscii(CStrVector("(^f|ob)"));
+ Handle<String> source = factory->NewStringFromStaticAscii("(^f|ob)");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
- Handle<String> input = factory->NewStringFromAscii(CStrVector("foobar"));
+ Handle<String> input = factory->NewStringFromStaticAscii("foobar");
Handle<SeqOneByteString> seq_input = Handle<SeqOneByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
@@ -1140,12 +1141,12 @@
m.Succeed();
Handle<String> source =
- factory->NewStringFromAscii(CStrVector("^(abc)\1\1(?!\1)...(?!\1)"));
+ factory->NewStringFromStaticAscii("^(abc)\1\1(?!\1)...(?!\1)");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
Handle<String> input =
- factory->NewStringFromAscii(CStrVector("aBcAbCABCxYzab"));
+ factory->NewStringFromStaticAscii("aBcAbCABCxYzab");
Handle<SeqOneByteString> seq_input = Handle<SeqOneByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
@@ -1241,13 +1242,13 @@
m.Fail();
Handle<String> source =
- factory->NewStringFromAscii(CStrVector("<loop test>"));
+ factory->NewStringFromStaticAscii("<loop test>");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
// String long enough for test (content doesn't matter).
Handle<String> input =
- factory->NewStringFromAscii(CStrVector("foofoofoofoofoo"));
+ factory->NewStringFromStaticAscii("foofoofoofoofoo");
Handle<SeqOneByteString> seq_input = Handle<SeqOneByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
@@ -1285,13 +1286,13 @@
m.GoTo(&loop);
Handle<String> source =
- factory->NewStringFromAscii(CStrVector("<stack overflow test>"));
+ factory->NewStringFromStaticAscii("<stack overflow test>");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
// String long enough for test (content doesn't matter).
Handle<String> input =
- factory->NewStringFromAscii(CStrVector("dummy"));
+ factory->NewStringFromStaticAscii("dummy");
Handle<SeqOneByteString> seq_input = Handle<SeqOneByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
@@ -1332,13 +1333,13 @@
m.Succeed();
Handle<String> source =
- factory->NewStringFromAscii(CStrVector("<huge register space test>"));
+ factory->NewStringFromStaticAscii("<huge register space test>");
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
// String long enough for test (content doesn't matter).
Handle<String> input =
- factory->NewStringFromAscii(CStrVector("sample text"));
+ factory->NewStringFromStaticAscii("sample text");
Handle<SeqOneByteString> seq_input = Handle<SeqOneByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
@@ -1400,13 +1401,13 @@
Factory* factory = isolate->factory();
HandleScope scope(isolate);
- Handle<String> source = factory->NewStringFromAscii(CStrVector("^f(o)o"));
+ Handle<String> source = factory->NewStringFromStaticAscii("^f(o)o");
Handle<ByteArray> array = Handle<ByteArray>::cast(m.GetCode(source));
int captures[5];
const uc16 str1[] = {'f', 'o', 'o', 'b', 'a', 'r'};
- Handle<String> f1_16 =
- factory->NewStringFromTwoByte(Vector<const uc16>(str1, 6));
+ Handle<String> f1_16 = factory->NewStringFromTwoByte(
+ Vector<const uc16>(str1, 6)).ToHandleChecked();
CHECK(IrregexpInterpreter::Match(isolate, array, f1_16, captures, 0));
CHECK_EQ(0, captures[0]);
@@ -1416,8 +1417,8 @@
CHECK_EQ(84, captures[4]);
const uc16 str2[] = {'b', 'a', 'r', 'f', 'o', 'o'};
- Handle<String> f2_16 =
- factory->NewStringFromTwoByte(Vector<const uc16>(str2, 6));
+ Handle<String> f2_16 = factory->NewStringFromTwoByte(
+ Vector<const uc16>(str2, 6)).ToHandleChecked();
CHECK(!IrregexpInterpreter::Match(isolate, array, f2_16, captures, 0));
CHECK_EQ(42, captures[0]);
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index c01a688..dd422d5 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -266,7 +266,7 @@
// Test that the whole heap can be serialized.
TEST(Serialize) {
if (!Snapshot::HaveASnapshotToStartFrom()) {
- Serializer::Enable(CcTest::i_isolate());
+ Serializer::RequestEnable(CcTest::i_isolate());
v8::V8::Initialize();
Serialize();
}
@@ -276,7 +276,7 @@
// Test that heap serialization is non-destructive.
TEST(SerializeTwice) {
if (!Snapshot::HaveASnapshotToStartFrom()) {
- Serializer::Enable(CcTest::i_isolate());
+ Serializer::RequestEnable(CcTest::i_isolate());
v8::V8::Initialize();
Serialize();
Serialize();
@@ -375,7 +375,7 @@
TEST(PartialSerialization) {
if (!Snapshot::HaveASnapshotToStartFrom()) {
Isolate* isolate = CcTest::i_isolate();
- Serializer::Enable(isolate);
+ Serializer::RequestEnable(isolate);
v8::V8::Initialize();
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
Heap* heap = isolate->heap();
@@ -526,7 +526,7 @@
TEST(ContextSerialization) {
if (!Snapshot::HaveASnapshotToStartFrom()) {
Isolate* isolate = CcTest::i_isolate();
- Serializer::Enable(isolate);
+ Serializer::RequestEnable(isolate);
v8::V8::Initialize();
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
Heap* heap = isolate->heap();
diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc
index d4dc516..1cfc28d 100644
--- a/test/cctest/test-strings.cc
+++ b/test/cctest/test-strings.cc
@@ -164,8 +164,8 @@
for (int j = 0; j < len; j++) {
buf[j] = rng->next(0x10000);
}
- building_blocks[i] =
- factory->NewStringFromTwoByte(Vector<const uc16>(buf, len));
+ building_blocks[i] = factory->NewStringFromTwoByte(
+ Vector<const uc16>(buf, len)).ToHandleChecked();
for (int j = 0; j < len; j++) {
CHECK_EQ(buf[j], building_blocks[i]->Get(j));
}
@@ -176,8 +176,8 @@
for (int j = 0; j < len; j++) {
buf[j] = rng->next(0x80);
}
- building_blocks[i] =
- factory->NewStringFromAscii(Vector<const char>(buf, len));
+ building_blocks[i] = factory->NewStringFromAscii(
+ Vector<const char>(buf, len)).ToHandleChecked();
for (int j = 0; j < len; j++) {
CHECK_EQ(buf[j], building_blocks[i]->Get(j));
}
@@ -463,7 +463,7 @@
ConsStringGenerationData* data,
int depth) {
Factory* factory = CcTest::i_isolate()->factory();
- Handle<String> answer = factory->NewStringFromAscii(CStrVector(""));
+ Handle<String> answer = factory->NewStringFromStaticAscii("");
data->stats_.leaves_++;
for (int i = 0; i < depth; i++) {
Handle<String> block = data->block(i);
@@ -482,7 +482,7 @@
ConsStringGenerationData* data,
int depth) {
Factory* factory = CcTest::i_isolate()->factory();
- Handle<String> answer = factory->NewStringFromAscii(CStrVector(""));
+ Handle<String> answer = factory->NewStringFromStaticAscii("");
data->stats_.leaves_++;
for (int i = depth - 1; i >= 0; i--) {
Handle<String> block = data->block(i);
@@ -870,9 +870,9 @@
for (int i = 0; i < DEEP_ASCII_DEPTH; i++) {
foo[i] = "foo "[i % 4];
}
- Handle<String> string =
- factory->NewStringFromAscii(Vector<const char>(foo, DEEP_ASCII_DEPTH));
- Handle<String> foo_string = factory->NewStringFromAscii(CStrVector("foo"));
+ Handle<String> string = factory->NewStringFromOneByte(
+ OneByteVector(foo, DEEP_ASCII_DEPTH)).ToHandleChecked();
+ Handle<String> foo_string = factory->NewStringFromStaticAscii("foo");
for (int i = 0; i < DEEP_ASCII_DEPTH; i += 10) {
string = factory->NewConsString(string, foo_string).ToHandleChecked();
}
@@ -1087,7 +1087,7 @@
CHECK_EQ(results[i]->IsUndefined(), result->IsUndefined());
CHECK_EQ(results[i]->IsNumber(), result->IsNumber());
if (result->IsNumber()) {
- CHECK_EQ(Smi::cast(results[i]->ToSmi()->ToObjectChecked())->value(),
+ CHECK_EQ(Handle<Smi>::cast(Object::ToSmi(isolate, results[i]))->value(),
result->ToInt32()->Value());
}
}
@@ -1100,7 +1100,7 @@
Factory* factory = CcTest::i_isolate()->factory();
v8::HandleScope scope(CcTest::isolate());
Handle<String> string =
- factory->NewStringFromAscii(CStrVector("parentparentparent"));
+ factory->NewStringFromStaticAscii("parentparentparent");
Handle<String> parent =
factory->NewConsString(string, string).ToHandleChecked();
CHECK(parent->IsConsString());
@@ -1212,7 +1212,7 @@
// Set heap limits.
static const int K = 1024;
v8::ResourceConstraints constraints;
- constraints.set_max_young_space_size(256 * K);
+ constraints.set_max_new_space_size(256 * K);
constraints.set_max_old_space_size(4 * K * K);
v8::SetResourceConstraints(CcTest::isolate(), &constraints);
diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc
index ba4748b..47868f6 100644
--- a/test/cctest/test-types.cc
+++ b/test/cctest/test-types.cc
@@ -43,7 +43,9 @@
static bool IsBitset(Type* t) { return reinterpret_cast<intptr_t>(t) & 1; }
static bool IsClass(Type* t) { return IsStruct(t, 0); }
static bool IsConstant(Type* t) { return IsStruct(t, 1); }
- static bool IsUnion(Type* t) { return IsStruct(t, 2); }
+ static bool IsArray(Type* t) { return IsStruct(t, 2); }
+ static bool IsFunction(Type* t) { return IsStruct(t, 3); }
+ static bool IsUnion(Type* t) { return IsStruct(t, 4); }
static Struct* AsStruct(Type* t) {
return reinterpret_cast<Struct*>(t);
@@ -77,7 +79,9 @@
static bool IsBitset(Handle<HeapType> t) { return t->IsSmi(); }
static bool IsClass(Handle<HeapType> t) { return t->IsMap(); }
static bool IsConstant(Handle<HeapType> t) { return t->IsBox(); }
- static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 2); }
+ static bool IsArray(Handle<HeapType> t) { return IsStruct(t, 2); }
+ static bool IsFunction(Handle<HeapType> t) { return IsStruct(t, 3); }
+ static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 4); }
static Struct* AsStruct(Handle<HeapType> t) { return FixedArray::cast(*t); }
static int AsBitset(Handle<HeapType> t) { return Smi::cast(*t)->value(); }
@@ -139,11 +143,31 @@
types.push_back(Type::Constant(*it, region));
}
- for (int i = 0; i < 100; ++i) {
+ FloatArray = Type::Array(Float, region);
+ StringArray = Type::Array(String, region);
+ AnyArray = Type::Array(Any, region);
+
+ SignedFunction1 = Type::Function(SignedSmall, SignedSmall, region);
+ NumberFunction1 = Type::Function(Number, Number, region);
+ NumberFunction2 = Type::Function(Number, Number, Number, region);
+ MethodFunction = Type::Function(String, Object, 0, region);
+
+ for (int i = 0; i < 50; ++i) {
types.push_back(Fuzz());
}
}
+ Handle<i::Map> object_map;
+ Handle<i::Map> array_map;
+ Handle<i::Map> uninitialized_map;
+
+ Handle<i::Smi> smi;
+ Handle<i::HeapNumber> signed32;
+ Handle<i::JSObject> object1;
+ Handle<i::JSObject> object2;
+ Handle<i::JSArray> array;
+ Handle<i::Oddball> uninitialized;
+
#define DECLARE_TYPE(name, value) TypeHandle name;
BITSET_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
@@ -159,16 +183,14 @@
TypeHandle ArrayConstant;
TypeHandle UninitializedConstant;
- Handle<i::Map> object_map;
- Handle<i::Map> array_map;
- Handle<i::Map> uninitialized_map;
+ TypeHandle FloatArray;
+ TypeHandle StringArray;
+ TypeHandle AnyArray;
- Handle<i::Smi> smi;
- Handle<i::HeapNumber> signed32;
- Handle<i::JSObject> object1;
- Handle<i::JSObject> object2;
- Handle<i::JSArray> array;
- Handle<i::Oddball> uninitialized;
+ TypeHandle SignedFunction1;
+ TypeHandle NumberFunction1;
+ TypeHandle NumberFunction2;
+ TypeHandle MethodFunction;
typedef std::vector<TypeHandle> TypeVector;
typedef std::vector<Handle<i::Map> > MapVector;
@@ -193,6 +215,24 @@
return Type::Class(map, region_);
}
+ TypeHandle Array1(TypeHandle element) {
+ return Type::Array(element, region_);
+ }
+
+ TypeHandle Function0(TypeHandle result, TypeHandle receiver) {
+ return Type::Function(result, receiver, 0, region_);
+ }
+
+ TypeHandle Function1(TypeHandle result, TypeHandle receiver, TypeHandle arg) {
+ TypeHandle type = Type::Function(result, receiver, 1, region_);
+ type->AsFunction()->InitParameter(0, arg);
+ return type;
+ }
+
+ TypeHandle Function2(TypeHandle result, TypeHandle arg1, TypeHandle arg2) {
+ return Type::Function(result, arg1, arg2, region_);
+ }
+
TypeHandle Union(TypeHandle t1, TypeHandle t2) {
return Type::Union(t1, t2, region_);
}
@@ -205,6 +245,10 @@
return Type::template Convert<Type2>(t, region_);
}
+ TypeHandle Random() {
+ return types[rng_.NextInt(static_cast<int>(types.size()))];
+ }
+
TypeHandle Fuzz(int depth = 5) {
switch (rng_.NextInt(depth == 0 ? 3 : 20)) {
case 0: { // bitset
@@ -228,11 +272,28 @@
int i = rng_.NextInt(static_cast<int>(values.size()));
return Type::Constant(values[i], region_);
}
+ case 3: { // array
+ TypeHandle element = Fuzz(depth / 2);
+ return Type::Array(element, region_);
+ }
+ case 4:
+ case 5:
+ case 6: { // function
+ TypeHandle result = Fuzz(depth / 2);
+ TypeHandle receiver = Fuzz(depth / 2);
+ int arity = rng_.NextInt(3);
+ TypeHandle type = Type::Function(result, receiver, arity, region_);
+ for (int i = 0; i < type->AsFunction()->Arity(); ++i) {
+ TypeHandle parameter = Fuzz(depth - 1);
+ type->AsFunction()->InitParameter(i, parameter);
+ }
+ }
default: { // union
int n = rng_.NextInt(10);
TypeHandle type = None;
for (int i = 0; i < n; ++i) {
- type = Type::Union(type, Fuzz(depth - 1), region_);
+ TypeHandle operand = Fuzz(depth - 1);
+ type = Type::Union(type, operand, region_);
}
return type;
}
@@ -406,7 +467,7 @@
for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
Handle<i::Map> map = *mt;
TypeHandle type = T.Class(map);
- CHECK(*map == *type->AsClass());
+ CHECK(*map == *type->AsClass()->Map());
}
// Functionality & Injectivity: Class(M1) = Class(M2) iff M1 = M2
@@ -433,10 +494,10 @@
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
TypeHandle type = T.Constant(value);
- CHECK(*value == *type->AsConstant());
+ CHECK(*value == *type->AsConstant()->Value());
}
- // Functionality & Injectivity: Constant(V1) = Constant(v2) iff V1 = V2
+ // Functionality & Injectivity: Constant(V1) = Constant(V2) iff V1 = V2
for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
Handle<i::Object> value1 = *vt1;
@@ -448,6 +509,102 @@
}
}
+ void Array() {
+ // Constructor
+ for (int i = 0; i < 20; ++i) {
+ TypeHandle type = T.Random();
+ TypeHandle array = T.Array1(type);
+ CHECK(this->IsArray(array));
+ }
+
+ // Attributes
+ for (int i = 0; i < 20; ++i) {
+ TypeHandle type = T.Random();
+ TypeHandle array = T.Array1(type);
+ CheckEqual(type, array->AsArray()->Element());
+ }
+
+ // Functionality & Injectivity: Array(T1) = Array(T2) iff T1 = T2
+ for (int i = 0; i < 20; ++i) {
+ for (int j = 0; j < 20; ++j) {
+ TypeHandle type1 = T.Random();
+ TypeHandle type2 = T.Random();
+ TypeHandle array1 = T.Array1(type1);
+ TypeHandle array2 = T.Array1(type2);
+ CHECK(Equal(array1, array2) == Equal(type1, type2));
+ }
+ }
+ }
+
+ void Function() {
+ // Constructors
+ for (int i = 0; i < 20; ++i) {
+ for (int j = 0; j < 20; ++j) {
+ for (int k = 0; k < 20; ++k) {
+ TypeHandle type1 = T.Random();
+ TypeHandle type2 = T.Random();
+ TypeHandle type3 = T.Random();
+ TypeHandle function0 = T.Function0(type1, type2);
+ TypeHandle function1 = T.Function1(type1, type2, type3);
+ TypeHandle function2 = T.Function2(type1, type2, type3);
+ CHECK(function0->IsFunction());
+ CHECK(function1->IsFunction());
+ CHECK(function2->IsFunction());
+ }
+ }
+ }
+
+ // Attributes
+ for (int i = 0; i < 20; ++i) {
+ for (int j = 0; j < 20; ++j) {
+ for (int k = 0; k < 20; ++k) {
+ TypeHandle type1 = T.Random();
+ TypeHandle type2 = T.Random();
+ TypeHandle type3 = T.Random();
+ TypeHandle function0 = T.Function0(type1, type2);
+ TypeHandle function1 = T.Function1(type1, type2, type3);
+ TypeHandle function2 = T.Function2(type1, type2, type3);
+ CHECK_EQ(0, function0->AsFunction()->Arity());
+ CHECK_EQ(1, function1->AsFunction()->Arity());
+ CHECK_EQ(2, function2->AsFunction()->Arity());
+ CheckEqual(type1, function0->AsFunction()->Result());
+ CheckEqual(type1, function1->AsFunction()->Result());
+ CheckEqual(type1, function2->AsFunction()->Result());
+ CheckEqual(type2, function0->AsFunction()->Receiver());
+ CheckEqual(type2, function1->AsFunction()->Receiver());
+ CheckEqual(T.Any, function2->AsFunction()->Receiver());
+ CheckEqual(type3, function1->AsFunction()->Parameter(0));
+ CheckEqual(type2, function2->AsFunction()->Parameter(0));
+ CheckEqual(type3, function2->AsFunction()->Parameter(1));
+ }
+ }
+ }
+
+ // Functionality & Injectivity: Function(Ts1) = Function(Ts2) iff Ts1 = Ts2
+ for (int i = 0; i < 20; ++i) {
+ for (int j = 0; j < 20; ++j) {
+ for (int k = 0; k < 20; ++k) {
+ TypeHandle type1 = T.Random();
+ TypeHandle type2 = T.Random();
+ TypeHandle type3 = T.Random();
+ TypeHandle function01 = T.Function0(type1, type2);
+ TypeHandle function02 = T.Function0(type1, type3);
+ TypeHandle function03 = T.Function0(type3, type2);
+ TypeHandle function11 = T.Function1(type1, type2, type2);
+ TypeHandle function12 = T.Function1(type1, type2, type3);
+ TypeHandle function21 = T.Function2(type1, type2, type2);
+ TypeHandle function22 = T.Function2(type1, type2, type3);
+ TypeHandle function23 = T.Function2(type1, type3, type2);
+ CHECK(Equal(function01, function02) == Equal(type2, type3));
+ CHECK(Equal(function01, function03) == Equal(type1, type3));
+ CHECK(Equal(function11, function12) == Equal(type2, type3));
+ CHECK(Equal(function21, function22) == Equal(type2, type3));
+ CHECK(Equal(function21, function23) == Equal(type2, type3));
+ }
+ }
+ }
+ }
+
void Of() {
// Constant(V)->Is(Of(V))
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
@@ -641,6 +798,7 @@
// Structural types
CheckSub(T.ObjectClass, T.Object);
CheckSub(T.ArrayClass, T.Object);
+ CheckSub(T.ArrayClass, T.Array);
CheckSub(T.UninitializedClass, T.Internal);
CheckUnordered(T.ObjectClass, T.ArrayClass);
CheckUnordered(T.UninitializedClass, T.Null);
@@ -664,6 +822,15 @@
CheckUnordered(T.ObjectConstant1, T.ArrayClass);
CheckUnordered(T.ObjectConstant2, T.ArrayClass);
CheckUnordered(T.ArrayConstant, T.ObjectClass);
+
+ CheckSub(T.FloatArray, T.Array);
+ CheckSub(T.FloatArray, T.Object);
+ CheckUnordered(T.StringArray, T.AnyArray);
+
+ CheckSub(T.MethodFunction, T.Function);
+ CheckSub(T.NumberFunction1, T.Object);
+ CheckUnordered(T.SignedFunction1, T.NumberFunction1);
+ CheckUnordered(T.NumberFunction1, T.NumberFunction2);
}
void NowIs() {
@@ -992,9 +1159,19 @@
CheckDisjoint(T.ObjectConstant1, T.ArrayClass, T.Semantic);
CheckDisjoint(T.ObjectConstant2, T.ArrayClass, T.Semantic);
CheckDisjoint(T.ArrayConstant, T.ObjectClass, T.Semantic);
+
+ CheckOverlap(T.FloatArray, T.Array, T.Semantic);
+ CheckDisjoint(T.FloatArray, T.AnyArray, T.Semantic);
+ CheckDisjoint(T.FloatArray, T.StringArray, T.Semantic);
+
+ CheckOverlap(T.MethodFunction, T.Function, T.Semantic);
+ CheckDisjoint(T.SignedFunction1, T.NumberFunction1, T.Semantic);
+ CheckDisjoint(T.SignedFunction1, T.NumberFunction2, T.Semantic);
+ CheckDisjoint(T.NumberFunction1, T.NumberFunction2, T.Semantic);
+ CheckDisjoint(T.SignedFunction1, T.MethodFunction, T.Semantic);
}
- void Union() {
+ void Union1() {
// Identity: Union(T, None) = T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
@@ -1063,7 +1240,9 @@
if (type1->Is(type2)) CheckEqual(union12, type2);
}
}
+ }
+ void Union2() {
// Monotonicity: T1->Is(T2) implies Union(T1, T3)->Is(Union(T2, T3))
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
@@ -1122,6 +1301,28 @@
CheckDisjoint(
T.Union(T.ObjectConstant1, T.ArrayConstant), T.ObjectClass, T.Semantic);
+ // Bitset-array
+ CHECK(this->IsBitset(T.Union(T.AnyArray, T.Array)));
+ CHECK(this->IsUnion(T.Union(T.FloatArray, T.Number)));
+
+ CheckEqual(T.Union(T.AnyArray, T.Array), T.Array);
+ CheckSub(T.None, T.Union(T.FloatArray, T.Number));
+ CheckSub(T.Union(T.FloatArray, T.Number), T.Any);
+ CheckUnordered(T.Union(T.AnyArray, T.String), T.Array);
+ CheckOverlap(T.Union(T.FloatArray, T.String), T.Object, T.Semantic);
+ CheckDisjoint(T.Union(T.FloatArray, T.String), T.Number, T.Semantic);
+
+ // Bitset-function
+ CHECK(this->IsBitset(T.Union(T.MethodFunction, T.Function)));
+ CHECK(this->IsUnion(T.Union(T.NumberFunction1, T.Number)));
+
+ CheckEqual(T.Union(T.MethodFunction, T.Function), T.Function);
+ CheckSub(T.None, T.Union(T.MethodFunction, T.Number));
+ CheckSub(T.Union(T.MethodFunction, T.Number), T.Any);
+ CheckUnordered(T.Union(T.NumberFunction1, T.String), T.Function);
+ CheckOverlap(T.Union(T.NumberFunction2, T.String), T.Object, T.Semantic);
+ CheckDisjoint(T.Union(T.NumberFunction1, T.String), T.Number, T.Semantic);
+
// Bitset-class
CheckSub(
T.Union(T.ObjectClass, T.SignedSmall), T.Union(T.Object, T.Number));
@@ -1177,6 +1378,18 @@
T.Union(
T.ObjectConstant2, T.Union(T.ArrayConstant, T.ObjectConstant1)));
+ // Array-union
+ CheckEqual(
+ T.Union(T.AnyArray, T.Union(T.FloatArray, T.AnyArray)),
+ T.Union(T.AnyArray, T.FloatArray));
+ CheckSub(T.Union(T.AnyArray, T.FloatArray), T.Array);
+
+ // Function-union
+ CheckEqual(
+ T.Union(T.NumberFunction1, T.NumberFunction2),
+ T.Union(T.NumberFunction2, T.NumberFunction1));
+ CheckSub(T.Union(T.SignedFunction1, T.MethodFunction), T.Function);
+
// Union-union
CheckEqual(
T.Union(
@@ -1190,7 +1403,7 @@
T.Union(T.Number, T.Array));
}
- void Intersect() {
+ void Intersect1() {
// Identity: Intersect(T, Any) = T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
@@ -1260,7 +1473,9 @@
if (type1->Is(type2)) CheckEqual(intersect12, type1);
}
}
+ }
+ void Intersect2() {
// Monotonicity: T1->Is(T2) implies Intersect(T1, T3)->Is(Intersect(T2, T3))
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
@@ -1308,9 +1523,13 @@
CheckSub(T.Intersect(T.ObjectClass, T.Array), T.Representation);
CheckSub(T.Intersect(T.ObjectClass, T.Number), T.Representation);
- // Class-constant
- CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectClass), T.None);
- CheckEqual(T.Intersect(T.ArrayClass, T.ObjectConstant2), T.None);
+ // Bitset-array
+ CheckEqual(T.Intersect(T.FloatArray, T.Object), T.FloatArray);
+ CheckSub(T.Intersect(T.AnyArray, T.Function), T.Representation);
+
+ // Bitset-function
+ CheckEqual(T.Intersect(T.MethodFunction, T.Object), T.MethodFunction);
+ CheckSub(T.Intersect(T.NumberFunction1, T.Array), T.Representation);
// Bitset-union
CheckEqual(
@@ -1320,6 +1539,32 @@
T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number),
T.None);
+ // Class-constant
+ CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectClass), T.None);
+ CheckEqual(T.Intersect(T.ArrayClass, T.ObjectConstant2), T.None);
+
+ // Array-union
+ CheckEqual(
+ T.Intersect(T.FloatArray, T.Union(T.FloatArray, T.ArrayClass)),
+ T.FloatArray);
+ CheckEqual(
+ T.Intersect(T.AnyArray, T.Union(T.Object, T.SmiConstant)),
+ T.AnyArray);
+ CheckEqual(
+ T.Intersect(T.Union(T.AnyArray, T.ArrayConstant), T.FloatArray),
+ T.None);
+
+ // Function-union
+ CheckEqual(
+ T.Intersect(T.MethodFunction, T.Union(T.String, T.MethodFunction)),
+ T.MethodFunction);
+ CheckEqual(
+ T.Intersect(T.NumberFunction1, T.Union(T.Object, T.SmiConstant)),
+ T.NumberFunction1);
+ CheckEqual(
+ T.Intersect(T.Union(T.MethodFunction, T.Name), T.NumberFunction2),
+ T.None);
+
// Class-union
CheckEqual(
T.Intersect(T.ArrayClass, T.Union(T.ObjectConstant2, T.ArrayClass)),
@@ -1387,27 +1632,41 @@
typedef Tests<HeapType, Handle<HeapType>, Isolate, HeapRep> HeapTests;
-TEST(Bitset) {
+TEST(BitsetType) {
CcTest::InitializeVM();
ZoneTests().Bitset();
HeapTests().Bitset();
}
-TEST(Class) {
+TEST(ClassType) {
CcTest::InitializeVM();
ZoneTests().Class();
HeapTests().Class();
}
-TEST(Constant) {
+TEST(ConstantType) {
CcTest::InitializeVM();
ZoneTests().Constant();
HeapTests().Constant();
}
+TEST(ArrayType) {
+ CcTest::InitializeVM();
+ ZoneTests().Array();
+ HeapTests().Array();
+}
+
+
+TEST(FunctionType) {
+ CcTest::InitializeVM();
+ ZoneTests().Function();
+ HeapTests().Function();
+}
+
+
TEST(Of) {
CcTest::InitializeVM();
ZoneTests().Of();
@@ -1457,17 +1716,31 @@
}
-TEST(Union) {
+TEST(Union1) {
CcTest::InitializeVM();
- ZoneTests().Union();
- HeapTests().Union();
+ ZoneTests().Union1();
+ HeapTests().Union1();
}
-TEST(Intersect) {
+TEST(Union2) {
CcTest::InitializeVM();
- ZoneTests().Intersect();
- HeapTests().Intersect();
+ ZoneTests().Union2();
+ HeapTests().Union2();
+}
+
+
+TEST(Intersect1) {
+ CcTest::InitializeVM();
+ ZoneTests().Intersect1();
+ HeapTests().Intersect1();
+}
+
+
+TEST(Intersect2) {
+ CcTest::InitializeVM();
+ ZoneTests().Intersect2();
+ HeapTests().Intersect2();
}
diff --git a/test/cctest/test-weakmaps.cc b/test/cctest/test-weakmaps.cc
index 61f6bf8..5eef214 100644
--- a/test/cctest/test-weakmaps.cc
+++ b/test/cctest/test-weakmaps.cc
@@ -187,8 +187,8 @@
Factory* factory = isolate->factory();
Heap* heap = isolate->heap();
HandleScope scope(isolate);
- Handle<JSFunction> function =
- factory->NewFunction(factory->function_string(), factory->null_value());
+ Handle<JSFunction> function = factory->NewFunctionWithPrototype(
+ factory->function_string(), factory->null_value());
Handle<JSObject> key = factory->NewJSObject(function);
Handle<JSWeakMap> weakmap = AllocateJSWeakMap(isolate);
@@ -227,8 +227,8 @@
Factory* factory = isolate->factory();
Heap* heap = isolate->heap();
HandleScope scope(isolate);
- Handle<JSFunction> function =
- factory->NewFunction(factory->function_string(), factory->null_value());
+ Handle<JSFunction> function = factory->NewFunctionWithPrototype(
+ factory->function_string(), factory->null_value());
// Start second old-space page so that keys land on evacuation candidate.
Page* first_page = heap->old_pointer_space()->anchor()->next_page();
diff --git a/test/cctest/test-weaksets.cc b/test/cctest/test-weaksets.cc
index c8f3bbf..9fa44c8 100644
--- a/test/cctest/test-weaksets.cc
+++ b/test/cctest/test-weaksets.cc
@@ -187,8 +187,8 @@
Factory* factory = isolate->factory();
Heap* heap = isolate->heap();
HandleScope scope(isolate);
- Handle<JSFunction> function =
- factory->NewFunction(factory->function_string(), factory->null_value());
+ Handle<JSFunction> function = factory->NewFunctionWithPrototype(
+ factory->function_string(), factory->null_value());
Handle<JSObject> key = factory->NewJSObject(function);
Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
@@ -227,8 +227,8 @@
Factory* factory = isolate->factory();
Heap* heap = isolate->heap();
HandleScope scope(isolate);
- Handle<JSFunction> function =
- factory->NewFunction(factory->function_string(), factory->null_value());
+ Handle<JSFunction> function = factory->NewFunctionWithPrototype(
+ factory->function_string(), factory->null_value());
// Start second old-space page so that keys land on evacuation candidate.
Page* first_page = heap->old_pointer_space()->anchor()->next_page();
diff --git a/test/mjsunit/array-push6.js b/test/mjsunit/array-push6.js
new file mode 100644
index 0000000..336b43d
--- /dev/null
+++ b/test/mjsunit/array-push6.js
@@ -0,0 +1,22 @@
+// 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 push_wrapper(array, value) {
+ array.push(value);
+}
+
+// Test that optimization of Array.push() for non-Arrays works correctly.
+var object = { x : 8, length: 3 };
+object[18] = 5;
+object.__proto__ = Array.prototype;
+push_wrapper(object, 1);
+push_wrapper(object, 1);
+assertEquals(5, object.length);
+%OptimizeFunctionOnNextCall(push_wrapper);
+push_wrapper(object, 1);
+push_wrapper(object, 1);
+assertEquals(8, object.x);
+assertEquals(7, object.length);
diff --git a/test/mjsunit/array-push7.js b/test/mjsunit/array-push7.js
new file mode 100644
index 0000000..b45a739
--- /dev/null
+++ b/test/mjsunit/array-push7.js
@@ -0,0 +1,59 @@
+// 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
+
+var v = 0;
+
+function push_wrapper(array, value) {
+ array.push(value);
+}
+function pop_wrapper(array) {
+ return array.pop();
+}
+
+// Test that Object.observe() notification events are properly sent from
+// Array.push() and Array.pop() both from optimized and un-optimized code.
+var array = [];
+
+function somethingChanged(changes) {
+ v++;
+}
+
+Object.observe(array, somethingChanged);
+push_wrapper(array, 1);
+%RunMicrotasks();
+assertEquals(1, array.length);
+assertEquals(1, v);
+push_wrapper(array, 1);
+%RunMicrotasks();
+assertEquals(2, array.length);
+assertEquals(2, v);
+%OptimizeFunctionOnNextCall(push_wrapper);
+push_wrapper(array, 1);
+%RunMicrotasks();
+assertEquals(3, array.length);
+assertEquals(3, v);
+push_wrapper(array, 1);
+%RunMicrotasks();
+assertEquals(4, array.length);
+assertEquals(4, v);
+
+pop_wrapper(array);
+%RunMicrotasks();
+assertEquals(3, array.length);
+assertEquals(5, v);
+pop_wrapper(array);
+%RunMicrotasks();
+assertEquals(2, array.length);
+assertEquals(6, v);
+%OptimizeFunctionOnNextCall(pop_wrapper);
+pop_wrapper(array);
+%RunMicrotasks();
+assertEquals(1, array.length);
+assertEquals(7, v);
+pop_wrapper(array);
+%RunMicrotasks();
+assertEquals(0, array.length);
+assertEquals(8, v);
diff --git a/test/mjsunit/array-push8.js b/test/mjsunit/array-push8.js
new file mode 100644
index 0000000..b1a8766
--- /dev/null
+++ b/test/mjsunit/array-push8.js
@@ -0,0 +1,37 @@
+// 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 push_wrapper(array, value) {
+ array.push(value);
+}
+function pop_wrapper(array) {
+ return array.pop();
+}
+
+// Test the frzon arrays throw an exception if you try to push to them, both in
+// optimized and non-optimized code.
+var array = [2, 2];
+Object.freeze(array);
+
+try { push_wrapper(array, 1); } catch (e) {}
+assertEquals(2, array.length);
+try { push_wrapper(array, 1); } catch (e) {}
+assertEquals(2, array.length);
+%OptimizeFunctionOnNextCall(push_wrapper);
+try { push_wrapper(array, 1); } catch (e) {}
+assertEquals(2, array.length);
+try { push_wrapper(array, 1); } catch (e) {}
+assertEquals(2, array.length);
+
+try { pop_wrapper(array); } catch (e) {}
+assertEquals(2, array.length);
+try { pop_wrapper(array); } catch (e) {}
+assertEquals(2, array.length);
+%OptimizeFunctionOnNextCall(pop_wrapper);
+try { pop_wrapper(array); } catch (e) {}
+assertEquals(2, array.length);
+try { pop_wrapper(array); } catch (e) {}
+assertEquals(2, array.length);
diff --git a/test/mjsunit/array-push9.js b/test/mjsunit/array-push9.js
new file mode 100644
index 0000000..d80cee8
--- /dev/null
+++ b/test/mjsunit/array-push9.js
@@ -0,0 +1,29 @@
+// 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=5 --nodead-code-elimination
+
+var array = [];
+
+function push(array, value) {
+ array.push(value);
+}
+
+push(array, 0);
+push(array, 1);
+push(array, 2);
+%OptimizeFunctionOnNextCall(push);
+push(array, 3);
+
+var v = 0;
+Object.defineProperty(Array.prototype, "4", {
+ get: function() { return 100; },
+ set: function(value) { v = value; }
+});
+
+push(array, 4);
+
+assertEquals(5, array.length);
+assertEquals(100, array[4]);
+assertEquals(4, v);
diff --git a/test/mjsunit/bugs/harmony/debug-blockscopes.js b/test/mjsunit/bugs/harmony/debug-blockscopes.js
index fda32eb..9ef8efb 100644
--- a/test/mjsunit/bugs/harmony/debug-blockscopes.js
+++ b/test/mjsunit/bugs/harmony/debug-blockscopes.js
@@ -144,18 +144,10 @@
if (!scope.scopeObject().property('arguments').isUndefined()) {
scope_size--;
}
- // Also ignore synthetic variable from catch block.
- if (!scope.scopeObject().property('.catch-var').isUndefined()) {
- scope_size--;
- }
// Skip property with empty name.
if (!scope.scopeObject().property('').isUndefined()) {
scope_size--;
}
- // Also ignore synthetic variable from block scopes.
- if (!scope.scopeObject().property('.block').isUndefined()) {
- scope_size--;
- }
if (count != scope_size) {
print('Names found in scope:');
diff --git a/test/mjsunit/debug-scopes.js b/test/mjsunit/debug-scopes.js
index f5b5ec9..ce37d24 100644
--- a/test/mjsunit/debug-scopes.js
+++ b/test/mjsunit/debug-scopes.js
@@ -166,10 +166,6 @@
if (!scope.scopeObject().property('arguments').isUndefined()) {
scope_size--;
}
- // Also ignore synthetic variable from catch block.
- if (!scope.scopeObject().property('.catch-var').isUndefined()) {
- scope_size--;
- }
// Skip property with empty name.
if (!scope.scopeObject().property('').isUndefined()) {
scope_size--;
diff --git a/test/mjsunit/field-type-tracking.js b/test/mjsunit/field-type-tracking.js
new file mode 100644
index 0000000..b4901f3
--- /dev/null
+++ b/test/mjsunit/field-type-tracking.js
@@ -0,0 +1,167 @@
+// 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 --nostress-opt --track-field-types
+
+(function() {
+ var o = { text: "Hello World!" };
+ function A() {
+ this.a = o;
+ }
+ function readA(x) {
+ return x.a;
+ }
+ var a = new A();
+ assertUnoptimized(readA);
+ readA(a); readA(a); readA(a);
+ %OptimizeFunctionOnNextCall(readA);
+ assertEquals(readA(a), o);
+ assertOptimized(readA);
+
+ var b = new A();
+ b.b = o;
+ assertEquals(readA(b), o);
+ assertUnoptimized(readA);
+ %OptimizeFunctionOnNextCall(readA);
+ assertEquals(readA(a), o);
+ assertOptimized(readA);
+ assertEquals(readA(a), o);
+ assertEquals(readA(b), o);
+ assertOptimized(readA);
+
+ function readAFromB(x) {
+ return x.a;
+ }
+ assertUnoptimized(readAFromB);
+ readAFromB(b); readAFromB(b); readAFromB(b);
+ %OptimizeFunctionOnNextCall(readAFromB);
+ assertEquals(readAFromB(b), o);
+ assertOptimized(readAFromB);
+
+ var c = new A();
+ c.c = o;
+ assertOptimized(readA);
+ assertOptimized(readAFromB);
+ c.a = [1];
+ assertUnoptimized(readA);
+ assertUnoptimized(readAFromB);
+ assertEquals(readA(a), o);
+ assertEquals(readA(b), o);
+ assertEquals(readA(c), [1]);
+ assertEquals(readAFromB(b), o);
+
+ %OptimizeFunctionOnNextCall(readA);
+ assertEquals(readA(a), o);
+ %OptimizeFunctionOnNextCall(readAFromB);
+ assertEquals(readAFromB(b), o);
+ assertOptimized(readA);
+ a.a = [1];
+ assertEquals(readA(a), [1]);
+ assertEquals(readA(b), o);
+ assertEquals(readA(c), [1]);
+ assertOptimized(readA);
+ b.a = [1];
+ assertEquals(readA(a), [1]);
+ assertEquals(readA(b), [1]);
+ assertEquals(readA(c), [1]);
+ assertOptimized(readA);
+ assertOptimized(readAFromB);
+})();
+
+(function() {
+ function A() { this.x = 0; }
+ A.prototype = {y: 20};
+ function B(o) { return o.a.y; }
+ function C() { this.a = new A(); }
+
+ B(new C());
+ B(new C());
+ %OptimizeFunctionOnNextCall(B);
+ var c = new C();
+ assertEquals(20, B(c));
+ assertOptimized(B);
+ c.a.y = 10;
+ assertEquals(10, B(c));
+ assertUnoptimized(B);
+
+ var c = new C();
+ %OptimizeFunctionOnNextCall(B);
+ assertEquals(20, B(c));
+ assertOptimized(B);
+ c.a.y = 30;
+ assertEquals(30, B(c));
+ assertOptimized(B);
+})();
+
+(function() {
+ var x = new Object();
+ x.a = 1 + "Long string that results in a cons string";
+ x = JSON.parse('{"a":"Short"}');
+})();
+
+(function() {
+ var x = {y: {z: 1}};
+ x.y.z = 1.1;
+})();
+
+(function() {
+ function Foo(x) { this.x = x; }
+ var f1 = new Foo({x: 1});
+ var f2 = new Foo({x: 2});
+ var f3 = new Foo({x: 3});
+ function readX(f) { return f.x.x; }
+ assertEquals(readX(f1), 1);
+ assertEquals(readX(f2), 2);
+ assertUnoptimized(readX);
+ %OptimizeFunctionOnNextCall(readX);
+ assertEquals(readX(f3), 3);
+ assertOptimized(readX);
+ function writeX(f, x) { f.x = x; }
+ writeX(f1, {x: 11});
+ writeX(f2, {x: 22});
+ assertUnoptimized(writeX);
+ assertEquals(readX(f1), 11);
+ assertEquals(readX(f2), 22);
+ assertOptimized(readX);
+ %OptimizeFunctionOnNextCall(writeX);
+ writeX(f3, {x: 33});
+ assertEquals(readX(f3), 33);
+ assertOptimized(readX);
+ assertOptimized(writeX);
+ function addY(f, y) { f.y = y; }
+ writeX(f1, {a: "a"});
+ assertUnoptimized(readX);
+ assertUnoptimized(writeX);
+})();
+
+(function() {
+ function Narf(x) { this.x = x; }
+ var f1 = new Narf(1);
+ var f2 = new Narf(2);
+ var f3 = new Narf(3);
+ function baz(f, y) { f.y = y; }
+ baz(f1, {y: 9});
+ baz(f2, {y: 9});
+ %OptimizeFunctionOnNextCall(baz);
+ baz(f3, {a: -1});
+ assertUnoptimized(baz);
+})();
+
+(function() {
+ function Foo(x) { this.x = x; this.a = x; }
+ function Bar(x) { this.x = x; this.b = x; }
+ function readA(o) { return o.x.a; }
+ var f = new Foo({a:1});
+ var b = new Bar({a:2});
+ assertEquals(readA(f), 1);
+ assertEquals(readA(b), 2);
+ assertEquals(readA(f), 1);
+ assertEquals(readA(b), 2);
+ %OptimizeFunctionOnNextCall(readA);
+ assertEquals(readA(f), 1);
+ assertEquals(readA(b), 2);
+ assertOptimized(readA);
+ f.a.y = 0;
+ assertUnoptimized(readA);
+})();
diff --git a/test/mjsunit/harmony/collections.js b/test/mjsunit/harmony/collections.js
index b33d080..002adaa 100644
--- a/test/mjsunit/harmony/collections.js
+++ b/test/mjsunit/harmony/collections.js
@@ -507,3 +507,347 @@
assertEquals('minus', m.get(0));
assertEquals('minus', m.get(-0));
})();
+
+
+(function TestSetForEachInvalidTypes() {
+ assertThrows(function() {
+ Set.prototype.set.forEach.call({});
+ }, TypeError);
+
+ var set = new Set();
+ assertThrows(function() {
+ set.forEach({});
+ }, TypeError);
+})();
+
+
+(function TestSetForEach() {
+ var set = new Set();
+ set.add('a');
+ set.add('b');
+ set.add('c');
+
+ var buffer = '';
+ var receiver = {};
+ set.forEach(function(v, k, s) {
+ assertSame(v, k);
+ assertSame(set, s);
+ assertSame(this, receiver);
+ buffer += v;
+ if (v === 'a') {
+ set.delete('b');
+ set.add('d');
+ set.add('e');
+ set.add('f');
+ } else if (v === 'c') {
+ set.add('b');
+ set.delete('e');
+ }
+ }, receiver);
+
+ assertEquals('acdfb', buffer);
+})();
+
+
+(function TestSetForEachAddAtEnd() {
+ var set = new Set();
+ set.add('a');
+ set.add('b');
+
+ var buffer = '';
+ set.forEach(function(v) {
+ buffer += v;
+ if (v === 'b') {
+ set.add('c');
+ }
+ });
+
+ assertEquals('abc', buffer);
+})();
+
+
+(function TestSetForEachDeleteNext() {
+ var set = new Set();
+ set.add('a');
+ set.add('b');
+ set.add('c');
+
+ var buffer = '';
+ set.forEach(function(v) {
+ buffer += v;
+ if (v === 'b') {
+ set.delete('c');
+ }
+ });
+
+ assertEquals('ab', buffer);
+})();
+
+
+(function TestSetForEachDeleteVisitedAndAddAgain() {
+ var set = new Set();
+ set.add('a');
+ set.add('b');
+ set.add('c');
+
+ var buffer = '';
+ set.forEach(function(v) {
+ buffer += v;
+ if (v === 'b') {
+ set.delete('a');
+ } else if (v === 'c') {
+ set.add('a');
+ }
+ });
+
+ assertEquals('abca', buffer);
+})();
+
+
+(function TestSetForEachClear() {
+ var set = new Set();
+ set.add('a');
+ set.add('b');
+ set.add('c');
+
+ var buffer = '';
+ set.forEach(function(v) {
+ buffer += v;
+ if (v === 'a') {
+ set.clear();
+ set.add('d');
+ set.add('e');
+ }
+ });
+
+ assertEquals('ade', buffer);
+})();
+
+
+(function TestSetForEachNested() {
+ var set = new Set();
+ set.add('a');
+ set.add('b');
+ set.add('c');
+
+ var buffer = '';
+ set.forEach(function(v) {
+ buffer += v;
+ set.forEach(function(v) {
+ buffer += v;
+ if (v === 'a') {
+ set.delete('b');
+ }
+ });
+ });
+
+ assertEquals('aaccac', buffer);
+})();
+
+
+(function TestSetForEachEarlyExit() {
+ var set = new Set();
+ set.add('a');
+ set.add('b');
+ set.add('c');
+
+ var buffer = '';
+ var ex = {};
+ try {
+ set.forEach(function(v) {
+ buffer += v;
+ throw ex;
+ });
+ } catch (e) {
+ assertEquals(ex, e);
+ }
+ assertEquals('a', buffer);
+})();
+
+
+(function TestSetForEachGC() {
+ var set = new Set();
+ for (var i = 0; i < 100; i++) {
+ set.add(i);
+ }
+
+ var accumulated = 0;
+ set.forEach(function(v) {
+ accumulated += v;
+ if (v % 10 === 0) {
+ gc();
+ }
+ });
+ assertEquals(4950, accumulated);
+})();
+
+(function TestMapForEachInvalidTypes() {
+ assertThrows(function() {
+ Map.prototype.map.forEach.call({});
+ }, TypeError);
+
+ var map = new Map();
+ assertThrows(function() {
+ map.forEach({});
+ }, TypeError);
+})();
+
+
+(function TestMapForEach() {
+ var map = new Map();
+ map.set(0, 'a');
+ map.set(1, 'b');
+ map.set(2, 'c');
+
+ var buffer = [];
+ var receiver = {};
+ map.forEach(function(v, k, m) {
+ assertEquals(map, m);
+ assertEquals(this, receiver);
+ buffer.push(k, v);
+ if (k === 0) {
+ map.delete(1);
+ map.set(3, 'd');
+ map.set(4, 'e');
+ map.set(5, 'f');
+ } else if (k === 2) {
+ map.set(1, 'B');
+ map.delete(4);
+ }
+ }, receiver);
+
+ assertArrayEquals([0, 'a', 2, 'c', 3, 'd', 5, 'f', 1, 'B'], buffer);
+})();
+
+
+(function TestMapForEachAddAtEnd() {
+ var map = new Map();
+ map.set(0, 'a');
+ map.set(1, 'b');
+
+ var buffer = [];
+ map.forEach(function(v, k) {
+ buffer.push(k, v);
+ if (k === 1) {
+ map.set(2, 'c');
+ }
+ });
+
+ assertArrayEquals([0, 'a', 1, 'b', 2, 'c'], buffer);
+})();
+
+
+(function TestMapForEachDeleteNext() {
+ var map = new Map();
+ map.set(0, 'a');
+ map.set(1, 'b');
+ map.set(2, 'c');
+
+ var buffer = [];
+ map.forEach(function(v, k) {
+ buffer.push(k, v);
+ if (k === 1) {
+ map.delete(2);
+ }
+ });
+
+ assertArrayEquals([0, 'a', 1, 'b'], buffer);
+})();
+
+
+(function TestSetForEachDeleteVisitedAndAddAgain() {
+ var map = new Map();
+ map.set(0, 'a');
+ map.set(1, 'b');
+ map.set(2, 'c');
+
+ var buffer = [];
+ map.forEach(function(v, k) {
+ buffer.push(k, v);
+ if (k === 1) {
+ map.delete(0);
+ } else if (k === 2) {
+ map.set(0, 'a');
+ }
+ });
+
+ assertArrayEquals([0, 'a', 1, 'b', 2, 'c', 0, 'a'], buffer);
+})();
+
+
+(function TestMapForEachClear() {
+ var map = new Map();
+ map.set(0, 'a');
+ map.set(1, 'b');
+ map.set(2, 'c');
+
+ var buffer = [];
+ map.forEach(function(v, k) {
+ buffer.push(k, v);
+ if (k === 0) {
+ map.clear();
+ map.set(3, 'd');
+ map.set(4, 'e');
+ }
+ });
+
+ assertArrayEquals([0, 'a', 3, 'd', 4, 'e'], buffer);
+})();
+
+
+(function TestMapForEachNested() {
+ var map = new Map();
+ map.set(0, 'a');
+ map.set(1, 'b');
+ map.set(2, 'c');
+
+ var buffer = [];
+ map.forEach(function(v, k) {
+ buffer.push(k, v);
+ map.forEach(function(v, k) {
+ buffer.push(k, v);
+ if (k === 0) {
+ map.delete(1);
+ }
+ });
+ });
+
+ assertArrayEquals([0, 'a', 0, 'a', 2, 'c', 2, 'c', 0, 'a', 2, 'c'], buffer);
+})();
+
+
+(function TestMapForEachEarlyExit() {
+ var map = new Map();
+ map.set(0, 'a');
+ map.set(1, 'b');
+ map.set(2, 'c');
+
+ var buffer = [];
+ var ex = {};
+ try {
+ map.forEach(function(v, k) {
+ buffer.push(k, v);
+ throw ex;
+ });
+ } catch (e) {
+ assertEquals(ex, e);
+ }
+ assertArrayEquals([0, 'a'], buffer);
+})();
+
+
+(function TestMapForEachGC() {
+ var map = new Map();
+ for (var i = 0; i < 100; i++) {
+ map.set(i, i);
+ }
+
+ var accumulated = 0;
+ map.forEach(function(v) {
+ accumulated += v;
+ if (v % 10 === 0) {
+ gc();
+ }
+ });
+ assertEquals(4950, accumulated);
+})();
diff --git a/test/mjsunit/harmony/debug-blockscopes.js b/test/mjsunit/harmony/debug-blockscopes.js
index ca2ab9e..f56a306 100644
--- a/test/mjsunit/harmony/debug-blockscopes.js
+++ b/test/mjsunit/harmony/debug-blockscopes.js
@@ -147,18 +147,10 @@
if (!scope.scopeObject().property('arguments').isUndefined()) {
scope_size--;
}
- // Also ignore synthetic variable from catch block.
- if (!scope.scopeObject().property('.catch-var').isUndefined()) {
- scope_size--;
- }
// Skip property with empty name.
if (!scope.scopeObject().property('').isUndefined()) {
scope_size--;
}
- // Also ignore synthetic variable from block scopes.
- if (!scope.scopeObject().property('.block').isUndefined()) {
- scope_size--;
- }
if (count != scope_size) {
print('Names found in scope:');
@@ -375,8 +367,9 @@
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:'y'}, 0, exec_state);
- // The function scope contains a temporary iteration variable.
- CheckScopeContent({'.for.x':'y'}, 1, exec_state);
+ // The function scope contains a temporary iteration variable, but it is
+ // hidden to the debugger.
+ CheckScopeContent({}, 1, exec_state);
};
for_loop_1();
EndTest();
@@ -400,8 +393,9 @@
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:3}, 0, exec_state);
CheckScopeContent({x:'y'}, 1, exec_state);
- // The function scope contains a temporary iteration variable.
- CheckScopeContent({'.for.x':'y'}, 2, exec_state);
+ // The function scope contains a temporary iteration variable, hidden to the
+ // debugger.
+ CheckScopeContent({}, 2, exec_state);
};
for_loop_2();
EndTest();
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index f604e1c..036fb48 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -70,7 +70,7 @@
##############################################################################
# These use a built-in that's only present in debug mode. They take
# too long to run in debug mode on ARM and MIPS.
- 'fuzz-natives-part*': [PASS, ['mode == release or arch == arm or arch == android_arm or arch == android_arm64 or arch == mipsel', SKIP]],
+ 'fuzz-natives-part*': [PASS, ['mode == release or arch == arm or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips', SKIP]],
'big-object-literal': [PASS, ['arch == arm or arch == android_arm or arch == android_arm64', SKIP]],
@@ -78,7 +78,7 @@
'array-constructor': [PASS, TIMEOUT],
# Very slow on ARM and MIPS, contains no architecture dependent code.
- 'unicode-case-overoptimization': [PASS, NO_VARIANTS, ['arch == arm or arch == android_arm or arch == android_arm64 or arch == mipsel', TIMEOUT]],
+ 'unicode-case-overoptimization': [PASS, NO_VARIANTS, ['arch == arm or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips', TIMEOUT]],
##############################################################################
# This test expects to reach a certain recursion depth, which may not work
@@ -122,6 +122,11 @@
# BUG(v8:2989). PASS/FAIL on linux32 because crankshaft is turned off for
# nosse2. Also for arm novfp3.
'regress/regress-2989': [FAIL, NO_VARIANTS, ['system == linux and arch == ia32 or arch == arm and simulator == True', PASS]],
+
+ # Skip endain dependent test for mips due to different typed views of the same
+ # array buffer.
+ 'nans': [PASS, ['arch == mips', SKIP]],
+
}], # ALWAYS
##############################################################################
@@ -168,9 +173,6 @@
'regress/regress-91013': [SKIP],
'regress/regress-99167': [SKIP],
- # TODO(ulan): enable this after relanding r20692.
- 'regress/regress-353058': [SKIP],
-
# Long running tests.
'regress/regress-2185': [PASS, ['mode == debug', PASS, TIMEOUT]],
'regress/regress-2185-2': [PASS, TIMEOUT],
@@ -237,8 +239,6 @@
'big-array-literal': [SKIP],
'big-object-literal': [SKIP],
'regress/regress-crbug-178790': [SKIP],
- # TODO(ulan): enable this after relanding r20692.
- 'regress/regress-353058': [SKIP],
}], # 'asan == True'
##############################################################################
@@ -269,9 +269,6 @@
'regress/regress-create-exception': [SKIP],
'regress/regress-3247124': [SKIP],
- # TODO(ulan): enable this after relanding r20692.
- 'regress/regress-353058': [SKIP],
-
# Requires bigger stack size in the Genesis and if stack size is increased,
# the test requires too much time to run. However, the problem test covers
# should be platform-independent.
@@ -300,7 +297,7 @@
}], # 'arch == arm or arch == android_arm'
##############################################################################
-['arch == mipsel', {
+['arch == mipsel or arch == mips', {
# Slow tests which times out in debug mode.
'try': [PASS, ['mode == debug', SKIP]],
@@ -336,7 +333,7 @@
# Currently always deopt on minus zero
'math-floor-of-div-minus-zero': [SKIP],
-}], # 'arch == mipsel'
+}], # 'arch == mipsel or arch == mips'
##############################################################################
# Native Client uses the ARM simulator so will behave similarly to arm
diff --git a/test/mjsunit/regress/regress-3280.js b/test/mjsunit/regress/regress-3280.js
new file mode 100644
index 0000000..2fc72cc
--- /dev/null
+++ b/test/mjsunit/regress/regress-3280.js
@@ -0,0 +1,25 @@
+// 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: --harmony-generators --expose-debug-as debug
+
+var Debug = debug.Debug;
+
+var listener_called;
+
+function listener(event, exec_state, event_data, data) {
+ if (event == Debug.DebugEvent.Break) {
+ listener_called = true;
+ exec_state.frame().allScopes();
+ }
+}
+
+Debug.setListener(listener);
+
+function *generator_local_2(a) {
+ debugger;
+}
+generator_local_2(1).next();
+
+assertTrue(listener_called, "listener not called");
diff --git a/test/mjsunit/regress/regress-3281.js b/test/mjsunit/regress/regress-3281.js
new file mode 100644
index 0000000..ebb2599
--- /dev/null
+++ b/test/mjsunit/regress/regress-3281.js
@@ -0,0 +1,13 @@
+// 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 --harmony-collections
+
+// Should not crash or raise an exception.
+
+var s = new Set();
+var setIterator = %SetCreateIterator(s, 2);
+
+var m = new Map();
+var mapIterator = %MapCreateIterator(m, 2);
diff --git a/test/mjsunit/regress/regress-363956.js b/test/mjsunit/regress/regress-363956.js
new file mode 100644
index 0000000..76d6728
--- /dev/null
+++ b/test/mjsunit/regress/regress-363956.js
@@ -0,0 +1,12 @@
+// 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 Fuu() { this.x = this.x.x; }
+Fuu.prototype.x = {x: 1}
+new Fuu();
+new Fuu();
+%OptimizeFunctionOnNextCall(Fuu);
+new Fuu();
diff --git a/test/mjsunit/regress/regress-builtinbust-4.js b/test/mjsunit/regress/regress-builtinbust-4.js
new file mode 100644
index 0000000..dbaa245
--- /dev/null
+++ b/test/mjsunit/regress/regress-builtinbust-4.js
@@ -0,0 +1,16 @@
+// 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.
+
+var o = { __proto__:Array.prototype, 0:"x" };
+function boomer() { return 0; }
+Object.defineProperty(o, "length", { get:boomer, set:boomer });
+Object.seal(o);
+
+assertDoesNotThrow(function() { o.push(1); });
+assertEquals(0, o.length);
+assertEquals(1, o[0]);
+
+assertDoesNotThrow(function() { o.unshift(2); });
+assertEquals(0, o.length);
+assertEquals(2, o[0]);
diff --git a/test/mjsunit/regress/regress-builtinbust-5.js b/test/mjsunit/regress/regress-builtinbust-5.js
new file mode 100644
index 0000000..266e4d4
--- /dev/null
+++ b/test/mjsunit/regress/regress-builtinbust-5.js
@@ -0,0 +1,13 @@
+// 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.
+
+var a = [ 1, 2, 3 ];
+var was_called = false;
+function poison() { was_called = true; }
+a.hasOwnProperty = poison;
+Object.freeze(a);
+
+assertThrows("a.unshift()", TypeError);
+assertEquals(3, a.length);
+assertFalse(was_called);
diff --git a/test/mjsunit/regress/regress-observe-map-cache.js b/test/mjsunit/regress/regress-observe-map-cache.js
new file mode 100644
index 0000000..4c7a7e3
--- /dev/null
+++ b/test/mjsunit/regress/regress-observe-map-cache.js
@@ -0,0 +1,14 @@
+// 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 --enable-slow-asserts
+
+function f() {
+ var x = new Array(0);
+ x[-1] = -1;
+ Object.observe(x, function() { });
+}
+
+f();
+f();
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index 04fc6a9..c04412a 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -141,8 +141,8 @@
'ecma/Date/15.9.5.28-1': [PASS, FAIL],
# 1050186: Arm/MIPS vm is broken; probably unrelated to dates
- 'ecma/Array/15.4.4.5-3': [PASS, ['arch == arm or arch == mipsel', FAIL]],
- 'ecma/Date/15.9.5.22-2': [PASS, ['arch == arm or arch == mipsel', FAIL]],
+ 'ecma/Array/15.4.4.5-3': [PASS, ['arch == arm or arch == mipsel or arch == mips', FAIL]],
+ 'ecma/Date/15.9.5.22-2': [PASS, ['arch == arm or arch == mipsel or arch == mips', FAIL]],
# Flaky test that fails due to what appears to be a bug in the test.
# Occurs depending on current time
@@ -874,6 +874,25 @@
'js1_5/GC/regress-203278-2': [PASS, TIMEOUT, NO_VARIANTS],
}], # 'arch == mipsel'
+['arch == mips', {
+
+ # BUG(3251229): Times out when running new crankshaft test script.
+ 'ecma_3/RegExp/regress-311414': [SKIP],
+ 'ecma/Date/15.9.5.8': [SKIP],
+ 'ecma/Date/15.9.5.10-2': [SKIP],
+ 'ecma/Date/15.9.5.11-2': [SKIP],
+ 'ecma/Date/15.9.5.12-2': [SKIP],
+ 'js1_5/Array/regress-99120-02': [SKIP],
+ 'js1_5/extensions/regress-371636': [SKIP],
+ 'js1_5/Regress/regress-203278-1': [SKIP],
+ 'js1_5/Regress/regress-404755': [SKIP],
+ 'js1_5/Regress/regress-451322': [SKIP],
+
+
+ # BUG(1040): Allow this test to timeout.
+ 'js1_5/GC/regress-203278-2': [PASS, TIMEOUT, NO_VARIANTS],
+}], # 'arch == mips'
+
['arch == arm64 and simulator_run == True', {
'js1_5/GC/regress-203278-2': [SKIP],
diff --git a/test/test262/test262.status b/test/test262/test262.status
index b844bdc..247bd5c 100644
--- a/test/test262/test262.status
+++ b/test/test262/test262.status
@@ -99,7 +99,7 @@
'S15.1.3.2_A2.5_T1': [PASS, ['mode == debug', SKIP]],
}], # ALWAYS
-['arch == arm or arch == mipsel or arch == arm64', {
+['arch == arm or arch == mipsel or arch == mips or arch == arm64', {
# TODO(mstarzinger): Causes stack overflow on simulators due to eager
# compilation of parenthesized function literals. Needs investigation.
@@ -112,5 +112,5 @@
'S15.1.3.2_A2.5_T1': [SKIP],
'S15.1.3.3_A2.3_T1': [SKIP],
'S15.1.3.4_A2.3_T1': [SKIP],
-}], # 'arch == arm or arch == mipsel or arch == arm64'
+}], # 'arch == arm or arch == mipsel or arch == mips or arch == arm64'
]
diff --git a/tools/gcmole/gcmole.lua b/tools/gcmole/gcmole.lua
index cd91a91..f1980a4 100644
--- a/tools/gcmole/gcmole.lua
+++ b/tools/gcmole/gcmole.lua
@@ -116,7 +116,7 @@
cfg.arch_define)
for _, filename in ipairs(filenames) do
log("-- %s", filename)
- local action = cmd_line .. " src/" .. filename .. " 2>&1"
+ local action = cmd_line .. " " .. filename .. " 2>&1"
if FLAGS.verbose then print('popen ', action) end
local pipe = io.popen(action)
func(filename, pipe:lines())
@@ -129,19 +129,26 @@
-- GYP file parsing
local function ParseGYPFile()
- local f = assert(io.open("tools/gyp/v8.gyp"), "failed to open GYP file")
- local gyp = f:read('*a')
- f:close()
+ local gyp = ""
+ local gyp_files = { "tools/gyp/v8.gyp", "test/cctest/cctest.gyp" }
+ for i = 1, #gyp_files do
+ local f = assert(io.open(gyp_files[i]), "failed to open GYP file")
+ local t = f:read('*a')
+ gyp = gyp .. t
+ f:close()
+ end
local result = {}
for condition, sources in
gyp:gmatch "'sources': %[.-### gcmole%((.-)%) ###(.-)%]" do
- local files = {}
+ if result[condition] == nil then result[condition] = {} end
for file in sources:gmatch "'%.%./%.%./src/([^']-%.cc)'" do
- table.insert(files, file)
+ table.insert(result[condition], "src/" .. file)
end
- result[condition] = files
+ for file in sources:gmatch "'(test-[^']-%.cc)'" do
+ table.insert(result[condition], "test/cctest/" .. file)
+ end
end
return result
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 77c331e..8dba67f 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -727,7 +727,7 @@
'../../src/ia32/stub-cache-ia32.cc',
],
}],
- ['v8_target_arch=="mipsel"', {
+ ['v8_target_arch=="mips" or v8_target_arch=="mipsel"', {
'sources': [ ### gcmole(arch:mipsel) ###
'../../src/mips/assembler-mips.cc',
'../../src/mips/assembler-mips.h',
diff --git a/tools/gyp/v8_base.arm.target.darwin-arm.mk b/tools/gyp/v8_base.arm.target.darwin-arm.mk
index 4994300..5a51cb5 100644
--- a/tools/gyp/v8_base.arm.target.darwin-arm.mk
+++ b/tools/gyp/v8_base.arm.target.darwin-arm.mk
@@ -429,7 +429,6 @@
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
-Wl,--icf=safe \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_base.arm.target.linux-arm.mk b/tools/gyp/v8_base.arm.target.linux-arm.mk
index 4994300..5a51cb5 100644
--- a/tools/gyp/v8_base.arm.target.linux-arm.mk
+++ b/tools/gyp/v8_base.arm.target.linux-arm.mk
@@ -429,7 +429,6 @@
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
-Wl,--icf=safe \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_base.ia32.target.darwin-x86.mk b/tools/gyp/v8_base.ia32.target.darwin-x86.mk
index 3bd658d..cb059a2 100644
--- a/tools/gyp/v8_base.ia32.target.darwin-x86.mk
+++ b/tools/gyp/v8_base.ia32.target.darwin-x86.mk
@@ -421,7 +421,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_base.ia32.target.linux-x86.mk b/tools/gyp/v8_base.ia32.target.linux-x86.mk
index 3bd658d..cb059a2 100644
--- a/tools/gyp/v8_base.ia32.target.linux-x86.mk
+++ b/tools/gyp/v8_base.ia32.target.linux-x86.mk
@@ -421,7 +421,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_base.mipsel.target.darwin-mips.mk b/tools/gyp/v8_base.mipsel.target.darwin-mips.mk
index 2f27429..8e0bc26 100644
--- a/tools/gyp/v8_base.mipsel.target.darwin-mips.mk
+++ b/tools/gyp/v8_base.mipsel.target.darwin-mips.mk
@@ -429,7 +429,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_base.mipsel.target.linux-mips.mk b/tools/gyp/v8_base.mipsel.target.linux-mips.mk
index 2f27429..8e0bc26 100644
--- a/tools/gyp/v8_base.mipsel.target.linux-mips.mk
+++ b/tools/gyp/v8_base.mipsel.target.linux-mips.mk
@@ -429,7 +429,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_base.x64.target.darwin-x86_64.mk b/tools/gyp/v8_base.x64.target.darwin-x86_64.mk
index 48fabdb..a0a5e18 100644
--- a/tools/gyp/v8_base.x64.target.darwin-x86_64.mk
+++ b/tools/gyp/v8_base.x64.target.darwin-x86_64.mk
@@ -421,7 +421,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_base.x64.target.linux-x86_64.mk b/tools/gyp/v8_base.x64.target.linux-x86_64.mk
index 48fabdb..a0a5e18 100644
--- a/tools/gyp/v8_base.x64.target.linux-x86_64.mk
+++ b/tools/gyp/v8_base.x64.target.linux-x86_64.mk
@@ -421,7 +421,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_snapshot.target.darwin-arm.mk b/tools/gyp/v8_snapshot.target.darwin-arm.mk
index 918bc6d..3f9fdc6 100644
--- a/tools/gyp/v8_snapshot.target.darwin-arm.mk
+++ b/tools/gyp/v8_snapshot.target.darwin-arm.mk
@@ -268,7 +268,6 @@
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
-Wl,--icf=safe \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_snapshot.target.darwin-mips.mk b/tools/gyp/v8_snapshot.target.darwin-mips.mk
index a50ae91..33f67a3 100644
--- a/tools/gyp/v8_snapshot.target.darwin-mips.mk
+++ b/tools/gyp/v8_snapshot.target.darwin-mips.mk
@@ -268,7 +268,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_snapshot.target.darwin-x86.mk b/tools/gyp/v8_snapshot.target.darwin-x86.mk
index 83cb838..a10ced2 100644
--- a/tools/gyp/v8_snapshot.target.darwin-x86.mk
+++ b/tools/gyp/v8_snapshot.target.darwin-x86.mk
@@ -262,7 +262,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_snapshot.target.darwin-x86_64.mk b/tools/gyp/v8_snapshot.target.darwin-x86_64.mk
index a78c914..223bcbe 100644
--- a/tools/gyp/v8_snapshot.target.darwin-x86_64.mk
+++ b/tools/gyp/v8_snapshot.target.darwin-x86_64.mk
@@ -262,7 +262,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_snapshot.target.linux-arm.mk b/tools/gyp/v8_snapshot.target.linux-arm.mk
index 918bc6d..3f9fdc6 100644
--- a/tools/gyp/v8_snapshot.target.linux-arm.mk
+++ b/tools/gyp/v8_snapshot.target.linux-arm.mk
@@ -268,7 +268,6 @@
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
-Wl,--icf=safe \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_snapshot.target.linux-mips.mk b/tools/gyp/v8_snapshot.target.linux-mips.mk
index a50ae91..33f67a3 100644
--- a/tools/gyp/v8_snapshot.target.linux-mips.mk
+++ b/tools/gyp/v8_snapshot.target.linux-mips.mk
@@ -268,7 +268,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_snapshot.target.linux-x86.mk b/tools/gyp/v8_snapshot.target.linux-x86.mk
index 83cb838..a10ced2 100644
--- a/tools/gyp/v8_snapshot.target.linux-x86.mk
+++ b/tools/gyp/v8_snapshot.target.linux-x86.mk
@@ -262,7 +262,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/gyp/v8_snapshot.target.linux-x86_64.mk b/tools/gyp/v8_snapshot.target.linux-x86_64.mk
index a78c914..223bcbe 100644
--- a/tools/gyp/v8_snapshot.target.linux-x86_64.mk
+++ b/tools/gyp/v8_snapshot.target.linux-x86_64.mk
@@ -262,7 +262,6 @@
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
diff --git a/tools/lexer-shell.cc b/tools/lexer-shell.cc
index e2e4a9c..273cdd9 100644
--- a/tools/lexer-shell.cc
+++ b/tools/lexer-shell.cc
@@ -67,16 +67,14 @@
Handle<String> result = isolate->factory()->NewStringFromTwoByte(
Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(source_),
- length / 2));
- CHECK_NOT_EMPTY_HANDLE(isolate, result);
+ length / 2)).ToHandleChecked();
stream_ =
new GenericStringUtf16CharacterStream(result, 0, result->length());
break;
}
case LATIN1: {
Handle<String> result = isolate->factory()->NewStringFromOneByte(
- Vector<const uint8_t>(source_, length));
- CHECK_NOT_EMPTY_HANDLE(isolate, result);
+ Vector<const uint8_t>(source_, length)).ToHandleChecked();
stream_ =
new GenericStringUtf16CharacterStream(result, 0, result->length());
break;
diff --git a/tools/push-to-trunk/releases.py b/tools/push-to-trunk/releases.py
index cb77337..578a9a1 100755
--- a/tools/push-to-trunk/releases.py
+++ b/tools/push-to-trunk/releases.py
@@ -168,6 +168,8 @@
"branch": branch,
# The version for displaying in the form 3.26.3 or 3.26.3.12.
"version": version,
+ # The date of the commit.
+ "date": self.GitLog(n=1, format="%ci", git_hash=git_hash),
# Merged patches if available in the form 'r1234, r2345'.
"patches_merged": patches,
# Default for easier output formatting.
diff --git a/tools/push-to-trunk/test_scripts.py b/tools/push-to-trunk/test_scripts.py
index 28d67b8..108d151 100644
--- a/tools/push-to-trunk/test_scripts.py
+++ b/tools/push-to-trunk/test_scripts.py
@@ -1191,6 +1191,7 @@
"Version 3.3.1.1 (merged 12)\n\nReview URL: fake.com\n"),
Git("log -1 --format=%s hash2", ""),
Git("svn find-rev hash2", "234"),
+ Git("log -1 --format=%ci hash2", "18:15"),
Git("checkout -f HEAD -- %s" % TEST_CONFIG[VERSION_FILE], "",
cb=ResetVersion(22, 5)),
Git("reset --hard svn/3.21", ""),
@@ -1201,6 +1202,7 @@
Git("log -1 --format=%B hash3", ""),
Git("log -1 --format=%s hash3", ""),
Git("svn find-rev hash3", "123"),
+ Git("log -1 --format=%ci hash3", "03:15"),
Git("checkout -f HEAD -- %s" % TEST_CONFIG[VERSION_FILE], "",
cb=ResetVersion(22, 5)),
Git("reset --hard svn/trunk", ""),
@@ -1211,6 +1213,7 @@
Git("log -1 --format=%B hash6", ""),
Git("log -1 --format=%s hash6", ""),
Git("svn find-rev hash6", "345"),
+ Git("log -1 --format=%ci hash6", ""),
Git("checkout -f HEAD -- %s" % TEST_CONFIG[VERSION_FILE], "",
cb=ResetVersion(22, 5)),
Git("status -s -uno", ""),
@@ -1247,15 +1250,15 @@
expected_json = [
{"bleeding_edge": "", "patches_merged": "", "version": "3.22.3",
"chromium_revision": "4567", "branch": "trunk", "revision": "345",
- "review_link": "",
+ "review_link": "", "date": "",
"revision_link": "https://code.google.com/p/v8/source/detail?r=345"},
{"patches_merged": "", "bleeding_edge": "", "version": "3.21.2",
"chromium_revision": "", "branch": "3.21", "revision": "123",
- "review_link": "",
+ "review_link": "", "date": "03:15",
"revision_link": "https://code.google.com/p/v8/source/detail?r=123"},
{"patches_merged": "12", "bleeding_edge": "", "version": "3.3.1.1",
"chromium_revision": "", "branch": "3.3", "revision": "234",
- "review_link": "fake.com",
+ "review_link": "fake.com", "date": "18:15",
"revision_link": "https://code.google.com/p/v8/source/detail?r=234"},
]
self.assertEquals(expected_json, json.loads(FileToText(json_output)))
diff --git a/tools/run-tests.py b/tools/run-tests.py
index b1b86ad..4167a55 100755
--- a/tools/run-tests.py
+++ b/tools/run-tests.py
@@ -80,6 +80,7 @@
"android_ia32",
"arm",
"ia32",
+ "mips",
"mipsel",
"nacl_ia32",
"nacl_x64",
@@ -90,6 +91,7 @@
"android_arm64",
"android_ia32",
"arm",
+ "mips",
"mipsel",
"nacl_ia32",
"nacl_x64",
diff --git a/tools/testrunner/local/statusfile.py b/tools/testrunner/local/statusfile.py
index 826b576..a45add3 100644
--- a/tools/testrunner/local/statusfile.py
+++ b/tools/testrunner/local/statusfile.py
@@ -53,8 +53,8 @@
# Support arches, modes to be written as keywords instead of strings.
VARIABLES = {ALWAYS: True}
for var in ["debug", "release", "android_arm", "android_arm64", "android_ia32",
- "arm", "arm64", "ia32", "mipsel", "x64", "nacl_ia32", "nacl_x64",
- "macos", "windows", "linux"]:
+ "arm", "arm64", "ia32", "mips", "mipsel", "x64", "nacl_ia32",
+ "nacl_x64", "macos", "windows", "linux"]:
VARIABLES[var] = var