Split even more runtime functions into separate files.

R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/612023002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24307 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2014-09-30 08:23:02 +00:00
parent aee775a509
commit 381616fb70
13 changed files with 3562 additions and 3498 deletions

View File

@ -827,7 +827,11 @@ source_set("v8_base") {
"src/runtime/runtime-collections.cc",
"src/runtime/runtime-compiler.cc",
"src/runtime/runtime-i18n.cc",
"src/runtime/runtime-date.cc",
"src/runtime/runtime-debug.cc",
"src/runtime/runtime-generator.cc",
"src/runtime/runtime-json.cc",
"src/runtime/runtime-liveedit.cc",
"src/runtime/runtime-maths.cc",
"src/runtime/runtime-numbers.cc",
"src/runtime/runtime-regexp.cc",

View File

@ -454,6 +454,10 @@ class Debug {
// Record function from which eval was called.
static void RecordEvalCaller(Handle<Script> script);
bool CheckExecutionState(int id) {
return !debug_context().is_null() && break_id() != 0 && break_id() == id;
}
// Flags and states.
DebugScope* debugger_entry() { return thread_local_.current_debug_scope_; }
inline Handle<Context> debug_context() { return debug_context_; }

View File

@ -1121,6 +1121,19 @@ MaybeHandle<Object> Object::GetElement(Isolate* isolate,
}
Handle<Object> Object::GetPrototypeSkipHiddenPrototypes(
Isolate* isolate, Handle<Object> receiver) {
PrototypeIterator iter(isolate, receiver);
while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
return PrototypeIterator::GetCurrent(iter);
}
iter.Advance();
}
return PrototypeIterator::GetCurrent(iter);
}
MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
Handle<Name> name) {
uint32_t index;

View File

@ -1167,6 +1167,9 @@ class Object {
Handle<Object> receiver,
uint32_t index);
static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
Isolate* isolate, Handle<Object> receiver);
// Returns the permanent hash code associated with this object. May return
// undefined if not yet created.
Object* GetHash();

View File

@ -9,12 +9,10 @@
#include "src/deoptimizer.h"
#include "src/frames.h"
#include "src/full-codegen.h"
#include "src/isolate.h"
#include "src/isolate-inl.h"
#include "src/runtime/runtime.h"
#include "src/runtime/runtime-utils.h"
#include "src/v8threads.h"
#include "src/vm-state.h"
#include "src/vm-state-inl.h"
namespace v8 {

190
src/runtime/runtime-date.cc Normal file
View File

@ -0,0 +1,190 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/v8.h"
#include "src/arguments.h"
#include "src/date.h"
#include "src/dateparser-inl.h"
#include "src/runtime/runtime.h"
#include "src/runtime/runtime-utils.h"
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_DateMakeDay) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(year, 0);
CONVERT_SMI_ARG_CHECKED(month, 1);
int days = isolate->date_cache()->DaysFromYearMonth(year, month);
RUNTIME_ASSERT(Smi::IsValid(days));
return Smi::FromInt(days);
}
RUNTIME_FUNCTION(Runtime_DateSetValue) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
CONVERT_DOUBLE_ARG_CHECKED(time, 1);
CONVERT_SMI_ARG_CHECKED(is_utc, 2);
DateCache* date_cache = isolate->date_cache();
Handle<Object> value;
;
bool is_value_nan = false;
if (std::isnan(time)) {
value = isolate->factory()->nan_value();
is_value_nan = true;
} else if (!is_utc && (time < -DateCache::kMaxTimeBeforeUTCInMs ||
time > DateCache::kMaxTimeBeforeUTCInMs)) {
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->factory()->nan_value();
is_value_nan = true;
} else {
value = isolate->factory()->NewNumber(DoubleToInteger(time));
}
}
date->SetValue(*value, is_value_nan);
return *value;
}
RUNTIME_FUNCTION(Runtime_ThrowNotDateError) {
HandleScope scope(isolate);
DCHECK(args.length() == 0);
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError("not_date_object", HandleVector<Object>(NULL, 0)));
}
RUNTIME_FUNCTION(Runtime_DateCurrentTime) {
HandleScope scope(isolate);
DCHECK(args.length() == 0);
if (FLAG_log_timer_events) LOG(isolate, CurrentTimeEvent());
// According to ECMA-262, section 15.9.1, page 117, the precision of
// the number in a Date object representing a particular instant in
// time is milliseconds. Therefore, we floor the result of getting
// the OS time.
double millis;
if (FLAG_verify_predictable) {
millis = 1388534400000.0; // Jan 1 2014 00:00:00 GMT+0000
millis += Floor(isolate->heap()->synthetic_time());
} else {
millis = Floor(base::OS::TimeCurrentMillis());
}
return *isolate->factory()->NewNumber(millis);
}
RUNTIME_FUNCTION(Runtime_DateParseString) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
RUNTIME_ASSERT(output->HasFastElements());
JSObject::EnsureCanContainHeapObjectElements(output);
RUNTIME_ASSERT(output->HasFastObjectElements());
Handle<FixedArray> output_array(FixedArray::cast(output->elements()));
RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
str = String::Flatten(str);
DisallowHeapAllocation no_gc;
bool result;
String::FlatContent str_content = str->GetFlatContent();
if (str_content.IsOneByte()) {
result = DateParser::Parse(str_content.ToOneByteVector(), *output_array,
isolate->unicode_cache());
} else {
DCHECK(str_content.IsTwoByte());
result = DateParser::Parse(str_content.ToUC16Vector(), *output_array,
isolate->unicode_cache());
}
if (result) {
return *output;
} else {
return isolate->heap()->null_value();
}
}
RUNTIME_FUNCTION(Runtime_DateLocalTimezone) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
RUNTIME_ASSERT(x >= -DateCache::kMaxTimeBeforeUTCInMs &&
x <= DateCache::kMaxTimeBeforeUTCInMs);
const char* zone =
isolate->date_cache()->LocalTimezone(static_cast<int64_t>(x));
Handle<String> result =
isolate->factory()->NewStringFromUtf8(CStrVector(zone)).ToHandleChecked();
return *result;
}
RUNTIME_FUNCTION(Runtime_DateToUTC) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
RUNTIME_ASSERT(x >= -DateCache::kMaxTimeBeforeUTCInMs &&
x <= DateCache::kMaxTimeBeforeUTCInMs);
int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
return *isolate->factory()->NewNumber(static_cast<double>(time));
}
RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
HandleScope hs(isolate);
DCHECK(args.length() == 0);
if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
Handle<FixedArray> date_cache_version =
isolate->factory()->NewFixedArray(1, TENURED);
date_cache_version->set(0, Smi::FromInt(0));
isolate->eternal_handles()->CreateSingleton(
isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
}
Handle<FixedArray> date_cache_version =
Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
EternalHandles::DATE_CACHE_VERSION));
// Return result as a JS array.
Handle<JSObject> result =
isolate->factory()->NewJSObject(isolate->array_function());
JSArray::SetContent(Handle<JSArray>::cast(result), date_cache_version);
return *result;
}
RUNTIME_FUNCTION(RuntimeReference_DateField) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_CHECKED(Object, obj, 0);
CONVERT_SMI_ARG_CHECKED(index, 1);
if (!obj->IsJSDate()) {
HandleScope scope(isolate);
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewTypeError("not_date_object", HandleVector<Object>(NULL, 0)));
}
JSDate* date = JSDate::cast(obj);
if (index == 0) return date->value();
return JSDate::GetField(date, Smi::FromInt(index));
}
}
} // namespace v8::internal

2736
src/runtime/runtime-debug.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,230 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/v8.h"
#include "src/arguments.h"
#include "src/frames-inl.h"
#include "src/runtime/runtime.h"
#include "src/runtime/runtime-utils.h"
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) {
HandleScope scope(isolate);
DCHECK(args.length() == 0);
JavaScriptFrameIterator it(isolate);
JavaScriptFrame* frame = it.frame();
Handle<JSFunction> function(frame->function());
RUNTIME_ASSERT(function->shared()->is_generator());
Handle<JSGeneratorObject> generator;
if (frame->IsConstructor()) {
generator = handle(JSGeneratorObject::cast(frame->receiver()));
} else {
generator = isolate->factory()->NewJSGeneratorObject(function);
}
generator->set_function(*function);
generator->set_context(Context::cast(frame->context()));
generator->set_receiver(frame->receiver());
generator->set_continuation(0);
generator->set_operand_stack(isolate->heap()->empty_fixed_array());
generator->set_stack_handler_index(-1);
return *generator;
}
RUNTIME_FUNCTION(Runtime_SuspendJSGeneratorObject) {
HandleScope handle_scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0);
JavaScriptFrameIterator stack_iterator(isolate);
JavaScriptFrame* frame = stack_iterator.frame();
RUNTIME_ASSERT(frame->function()->shared()->is_generator());
DCHECK_EQ(frame->function(), generator_object->function());
// The caller should have saved the context and continuation already.
DCHECK_EQ(generator_object->context(), Context::cast(frame->context()));
DCHECK_LT(0, generator_object->continuation());
// We expect there to be at least two values on the operand stack: the return
// value of the yield expression, and the argument to this runtime call.
// Neither of those should be saved.
int operands_count = frame->ComputeOperandsCount();
DCHECK_GE(operands_count, 2);
operands_count -= 2;
if (operands_count == 0) {
// Although it's semantically harmless to call this function with an
// operands_count of zero, it is also unnecessary.
DCHECK_EQ(generator_object->operand_stack(),
isolate->heap()->empty_fixed_array());
DCHECK_EQ(generator_object->stack_handler_index(), -1);
// If there are no operands on the stack, there shouldn't be a handler
// active either.
DCHECK(!frame->HasHandler());
} else {
int stack_handler_index = -1;
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);
}
return isolate->heap()->undefined_value();
}
// Note that this function is the slow path for resuming generators. It is only
// called if the suspended activation had operands on the stack, stack handlers
// needing rewinding, or if the resume should throw an exception. The fast path
// is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
// 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(Runtime_ResumeJSGeneratorObject) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
CONVERT_ARG_CHECKED(Object, value, 1);
CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
JavaScriptFrameIterator stack_iterator(isolate);
JavaScriptFrame* frame = stack_iterator.frame();
DCHECK_EQ(frame->function(), generator_object->function());
DCHECK(frame->function()->is_compiled());
STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
Address pc = generator_object->function()->code()->instruction_start();
int offset = generator_object->continuation();
DCHECK(offset > 0);
frame->set_pc(pc + offset);
if (FLAG_enable_ool_constant_pool) {
frame->set_constant_pool(
generator_object->function()->code()->constant_pool());
}
generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
FixedArray* operand_stack = generator_object->operand_stack();
int operands_count = operand_stack->length();
if (operands_count != 0) {
frame->RestoreOperandStack(operand_stack,
generator_object->stack_handler_index());
generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
generator_object->set_stack_handler_index(-1);
}
JSGeneratorObject::ResumeMode resume_mode =
static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
switch (resume_mode) {
case JSGeneratorObject::NEXT:
return value;
case JSGeneratorObject::THROW:
return isolate->Throw(value);
}
UNREACHABLE();
return isolate->ThrowIllegalOperation();
}
RUNTIME_FUNCTION(Runtime_ThrowGeneratorStateError) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
int continuation = generator->continuation();
const char* message = continuation == JSGeneratorObject::kGeneratorClosed
? "generator_finished"
: "generator_running";
Vector<Handle<Object> > argv = HandleVector<Object>(NULL, 0);
THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewError(message, argv));
}
// Returns function of generator activation.
RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
return generator->function();
}
// Returns context of generator activation.
RUNTIME_FUNCTION(Runtime_GeneratorGetContext) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
return generator->context();
}
// Returns receiver of generator activation.
RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
return generator->receiver();
}
// Returns generator continuation as a PC offset, or the magic -1 or 0 values.
RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
return Smi::FromInt(generator->continuation());
}
RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
if (generator->is_suspended()) {
Handle<Code> code(generator->function()->code(), isolate);
int offset = generator->continuation();
RUNTIME_ASSERT(0 <= offset && offset < code->Size());
Address pc = code->address() + offset;
return Smi::FromInt(code->SourcePosition(pc));
}
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_FunctionIsGenerator) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, f, 0);
return isolate->heap()->ToBoolean(f->shared()->is_generator());
}
RUNTIME_FUNCTION(RuntimeReference_GeneratorNext) {
UNREACHABLE(); // Optimization disabled in SetUpGenerators().
return NULL;
}
RUNTIME_FUNCTION(RuntimeReference_GeneratorThrow) {
UNREACHABLE(); // Optimization disabled in SetUpGenerators().
return NULL;
}
}
} // namespace v8::internal

View File

@ -0,0 +1,293 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/v8.h"
#include "src/arguments.h"
#include "src/debug.h"
#include "src/liveedit.h"
#include "src/runtime/runtime.h"
#include "src/runtime/runtime-utils.h"
namespace v8 {
namespace internal {
static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
Script* script,
FixedArray* buffer) {
DisallowHeapAllocation no_allocation;
int counter = 0;
int buffer_size = buffer->length();
for (HeapObject* obj = iterator->next(); obj != NULL;
obj = iterator->next()) {
DCHECK(obj != NULL);
if (!obj->IsSharedFunctionInfo()) {
continue;
}
SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
if (shared->script() != script) {
continue;
}
if (counter < buffer_size) {
buffer->set(counter, shared);
}
counter++;
}
return counter;
}
// For a script finds all SharedFunctionInfo's in the heap that points
// to this script. Returns JSArray of SharedFunctionInfo wrapped
// in OpaqueReferences.
RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(JSValue, script_value, 0);
RUNTIME_ASSERT(script_value->value()->IsScript());
Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
const int kBufferSize = 32;
Handle<FixedArray> array;
array = isolate->factory()->NewFixedArray(kBufferSize);
int number;
Heap* heap = isolate->heap();
{
HeapIterator heap_iterator(heap);
Script* scr = *script;
FixedArray* arr = *array;
number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
}
if (number > kBufferSize) {
array = isolate->factory()->NewFixedArray(number);
HeapIterator heap_iterator(heap);
Script* scr = *script;
FixedArray* arr = *array;
FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
}
Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
result->set_length(Smi::FromInt(number));
LiveEdit::WrapSharedFunctionInfos(result);
return *result;
}
// For a script calculates compilation information about all its functions.
// The script source is explicitly specified by the second argument.
// The source of the actual script is not used, however it is important that
// all generated code keeps references to this particular instance of script.
// 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(Runtime_LiveEditGatherCompileInfo) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 2);
CONVERT_ARG_CHECKED(JSValue, script, 0);
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
RUNTIME_ASSERT(script->value()->IsScript());
Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
Handle<JSArray> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, LiveEdit::GatherCompileInfo(script_handle, source));
return *result;
}
// 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(Runtime_LiveEditReplaceScript) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 3);
CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
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()));
Handle<Object> old_script = LiveEdit::ChangeScriptSource(
original_script, new_source, old_script_name);
if (old_script->IsScript()) {
Handle<Script> script_handle = Handle<Script>::cast(old_script);
return *Script::GetWrapper(script_handle);
} else {
return isolate->heap()->null_value();
}
}
RUNTIME_FUNCTION(Runtime_LiveEditFunctionSourceUpdated) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info));
LiveEdit::FunctionSourceUpdated(shared_info);
return isolate->heap()->undefined_value();
}
// Replaces code of SharedFunctionInfo with a new one.
RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info));
LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
return isolate->heap()->undefined_value();
}
// Connects SharedFunctionInfo to another script.
RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 2);
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);
if (script_object->IsJSValue()) {
RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
Script* script = Script::cast(JSValue::cast(*script_object)->value());
script_object = Handle<Object>(script, isolate);
}
RUNTIME_ASSERT(function_wrapper->value()->IsSharedFunctionInfo());
LiveEdit::SetFunctionScript(function_wrapper, script_object);
} else {
// Just ignore this. We may not have a SharedFunctionInfo for some functions
// and we check it in this function.
}
return isolate->heap()->undefined_value();
}
// In a code of a parent function replaces original function as embedded object
// with a substitution one.
RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
RUNTIME_ASSERT(parent_wrapper->value()->IsSharedFunctionInfo());
RUNTIME_ASSERT(orig_wrapper->value()->IsSharedFunctionInfo());
RUNTIME_ASSERT(subst_wrapper->value()->IsSharedFunctionInfo());
LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
subst_wrapper);
return isolate->heap()->undefined_value();
}
// Updates positions of a shared function info (first parameter) according
// to script source change. Text change is described in second parameter as
// 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(Runtime_LiveEditPatchFunctionPositions) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_array))
LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
return isolate->heap()->undefined_value();
}
// For array of SharedFunctionInfo's (each wrapped in JSValue)
// 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(Runtime_LiveEditCheckAndDropActivations) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
RUNTIME_ASSERT(shared_array->length()->IsSmi());
RUNTIME_ASSERT(shared_array->HasFastElements())
int array_length = Smi::cast(shared_array->length())->value();
for (int i = 0; i < array_length; i++) {
Handle<Object> element =
Object::GetElement(isolate, shared_array, i).ToHandleChecked();
RUNTIME_ASSERT(
element->IsJSValue() &&
Handle<JSValue>::cast(element)->value()->IsSharedFunctionInfo());
}
return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
}
// 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(Runtime_LiveEditCompareStrings) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
return *LiveEdit::CompareStrings(s1, s2);
}
// Restarts a call frame and completely drops all frames above.
// Returns true if successful. Otherwise returns undefined or an error message.
RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK(args.length() == 2);
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
Heap* heap = isolate->heap();
// Find the relevant frame with the requested index.
StackFrame::Id id = isolate->debug()->break_frame_id();
if (id == StackFrame::NO_ID) {
// If there are no JavaScript stack frames return undefined.
return heap->undefined_value();
}
JavaScriptFrameIterator it(isolate, id);
int inlined_jsframe_index = FindIndexedNonNativeFrame(&it, index);
if (inlined_jsframe_index == -1) return heap->undefined_value();
// We don't really care what the inlined frame index is, since we are
// throwing away the entire frame anyways.
const char* error_message = LiveEdit::RestartFrame(it.frame());
if (error_message) {
return *(isolate->factory()->InternalizeUtf8String(error_message));
}
return heap->true_value();
}
}
} // namespace v8::internal

View File

@ -292,6 +292,61 @@ RUNTIME_FUNCTION(Runtime_AbortJS) {
}
// Returns V8 version as a string.
RUNTIME_FUNCTION(Runtime_GetV8Version) {
HandleScope scope(isolate);
DCHECK(args.length() == 0);
const char* version_string = v8::V8::GetVersion();
return *isolate->factory()->NewStringFromAsciiChecked(version_string);
}
#ifdef DEBUG
// ListNatives is ONLY used by the fuzz-natives.js in debug mode
// Exclude the code in release mode.
RUNTIME_FUNCTION(Runtime_ListNatives) {
HandleScope scope(isolate);
DCHECK(args.length() == 0);
#define COUNT_ENTRY(Name, argc, ressize) +1
int entry_count =
0 RUNTIME_FUNCTION_LIST(COUNT_ENTRY) INLINE_FUNCTION_LIST(COUNT_ENTRY)
INLINE_OPTIMIZED_FUNCTION_LIST(COUNT_ENTRY);
#undef COUNT_ENTRY
Factory* factory = isolate->factory();
Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
int index = 0;
bool inline_runtime_functions = false;
#define ADD_ENTRY(Name, argc, ressize) \
{ \
HandleScope inner(isolate); \
Handle<String> name; \
/* Inline runtime functions have an underscore in front of the name. */ \
if (inline_runtime_functions) { \
name = factory->NewStringFromStaticChars("_" #Name); \
} else { \
name = factory->NewStringFromStaticChars(#Name); \
} \
Handle<FixedArray> pair_elements = factory->NewFixedArray(2); \
pair_elements->set(0, *name); \
pair_elements->set(1, Smi::FromInt(argc)); \
Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements); \
elements->set(index++, *pair); \
}
inline_runtime_functions = false;
RUNTIME_FUNCTION_LIST(ADD_ENTRY)
INLINE_OPTIMIZED_FUNCTION_LIST(ADD_ENTRY)
inline_runtime_functions = true;
INLINE_FUNCTION_LIST(ADD_ENTRY)
#undef ADD_ENTRY
DCHECK_EQ(index, entry_count);
Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
return *result;
}
#endif
RUNTIME_FUNCTION(Runtime_HaveSameMap) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 2);
@ -319,5 +374,27 @@ ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
#undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
#define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \
RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \
CONVERT_ARG_CHECKED(JSObject, obj, 0); \
return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \
}
TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
#undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
#define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \
CONVERT_ARG_CHECKED(JSObject, obj, 0); \
return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
}
TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
#undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
}
} // namespace v8::internal

View File

@ -140,6 +140,10 @@ static inline ObjectPair MakePair(Object* x, Object* y) {
#endif
}
#endif
class JavaScriptFrameIterator;
int FindIndexedNonNativeFrame(JavaScriptFrameIterator* it, int index);
}
} // namespace v8::internal

File diff suppressed because it is too large Load Diff

View File

@ -737,8 +737,12 @@
'../../src/runtime-profiler.h',
'../../src/runtime/runtime-collections.cc',
'../../src/runtime/runtime-compiler.cc',
'../../src/runtime/runtime-date.cc',
'../../src/runtime/runtime-debug.cc',
'../../src/runtime/runtime-generator.cc',
'../../src/runtime/runtime-i18n.cc',
'../../src/runtime/runtime-json.cc',
'../../src/runtime/runtime-liveedit.cc',
'../../src/runtime/runtime-maths.cc',
'../../src/runtime/runtime-numbers.cc',
'../../src/runtime/runtime-regexp.cc',