Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/debug/arm/debug-arm.cc b/src/debug/arm/debug-arm.cc
index fa3540e..29e4827 100644
--- a/src/debug/arm/debug-arm.cc
+++ b/src/debug/arm/debug-arm.cc
@@ -41,7 +41,7 @@
void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
Handle<Code> code) {
- DCHECK_EQ(Code::BUILTIN, code->kind());
+ DCHECK(code->is_debug_stub());
CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions);
// Patch the code changing the debug break slot code from
// mov r2, r2
diff --git a/src/debug/arm64/debug-arm64.cc b/src/debug/arm64/debug-arm64.cc
index cd01721..bf7964a 100644
--- a/src/debug/arm64/debug-arm64.cc
+++ b/src/debug/arm64/debug-arm64.cc
@@ -43,7 +43,7 @@
void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
Handle<Code> code) {
- DCHECK_EQ(Code::BUILTIN, code->kind());
+ DCHECK(code->is_debug_stub());
PatchingAssembler patcher(isolate, reinterpret_cast<Instruction*>(pc),
Assembler::kDebugBreakSlotInstructions);
// Patch the code emitted by DebugCodegen::GenerateSlots, changing the debug
diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc
index d5ebaa5..62b7a2b 100644
--- a/src/debug/debug-evaluate.cc
+++ b/src/debug/debug-evaluate.cc
@@ -250,7 +250,7 @@
// referenced by the current function, so it can be correctly resolved.
return;
} else if (local_function->shared()->scope_info()->HasReceiver() &&
- !frame_->receiver()->IsTheHole()) {
+ !frame_->receiver()->IsTheHole(isolate_)) {
recv = handle(frame_->receiver(), isolate_);
}
JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check();
diff --git a/src/debug/debug-frames.cc b/src/debug/debug-frames.cc
index 453a77d..b1a8af2 100644
--- a/src/debug/debug-frames.cc
+++ b/src/debug/debug-frames.cc
@@ -123,7 +123,7 @@
i < GetParametersCount()
? GetParameter(i)
: Handle<Object>::cast(isolate_->factory()->undefined_value());
- DCHECK(!value->IsTheHole());
+ DCHECK(!value->IsTheHole(isolate_));
JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
}
@@ -135,8 +135,12 @@
Handle<Object> value = GetExpression(scope_info->StackLocalIndex(i));
// TODO(yangguo): We convert optimized out values to {undefined} when they
// are passed to the debugger. Eventually we should handle them somehow.
- if (value->IsTheHole()) value = isolate_->factory()->undefined_value();
- if (value->IsOptimizedOut()) value = isolate_->factory()->undefined_value();
+ if (value->IsTheHole(isolate_)) {
+ value = isolate_->factory()->undefined_value();
+ }
+ if (value->IsOptimizedOut(isolate_)) {
+ value = isolate_->factory()->undefined_value();
+ }
JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
}
}
@@ -166,7 +170,7 @@
if (ScopeInfo::VariableIsSynthetic(*name)) continue;
if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
- DCHECK(!frame_->GetParameter(i)->IsTheHole());
+ DCHECK(!frame_->GetParameter(i)->IsTheHole(isolate_));
Handle<Object> value =
Object::GetPropertyOrElement(target, name).ToHandleChecked();
frame_->SetParameterValue(i, *value);
@@ -177,7 +181,7 @@
Handle<String> name(scope_info->StackLocalName(i));
if (ScopeInfo::VariableIsSynthetic(*name)) continue;
int index = scope_info->StackLocalIndex(i);
- if (frame_->GetExpression(index)->IsTheHole()) continue;
+ if (frame_->GetExpression(index)->IsTheHole(isolate_)) continue;
Handle<Object> value =
Object::GetPropertyOrElement(target, name).ToHandleChecked();
frame_->SetExpression(index, *value);
diff --git a/src/debug/debug-scopes.cc b/src/debug/debug-scopes.cc
index 1602711..400b1e1 100644
--- a/src/debug/debug-scopes.cc
+++ b/src/debug/debug-scopes.cc
@@ -34,7 +34,7 @@
Handle<JSFunction> function = GetFunction();
Handle<SharedFunctionInfo> shared_info(function->shared());
Handle<ScopeInfo> scope_info(shared_info->scope_info());
- if (shared_info->script() == isolate->heap()->undefined_value()) {
+ if (shared_info->script()->IsUndefined(isolate)) {
while (context_->closure() == *function) {
context_ = Handle<Context>(context_->previous(), isolate_);
}
@@ -494,7 +494,7 @@
if (function_context->closure() == *function &&
!function_context->IsNativeContext()) {
CopyContextExtensionToScopeObject(function_context, local_scope,
- INCLUDE_PROTOS);
+ KeyCollectionMode::kIncludePrototypes);
}
return local_scope;
@@ -520,7 +520,8 @@
// Finally copy any properties from the function context extension. This will
// be variables introduced by eval.
- CopyContextExtensionToScopeObject(context, closure_scope, OWN_ONLY);
+ CopyContextExtensionToScopeObject(context, closure_scope,
+ KeyCollectionMode::kOwnOnly);
return closure_scope;
}
@@ -571,7 +572,8 @@
if (!context.is_null()) {
// Fill all context locals.
CopyContextLocalsToScopeObject(CurrentScopeInfo(), context, inner_scope);
- CopyContextExtensionToScopeObject(context, inner_scope, OWN_ONLY);
+ CopyContextExtensionToScopeObject(context, inner_scope,
+ KeyCollectionMode::kOwnOnly);
}
return inner_scope;
}
@@ -754,7 +756,7 @@
int context_index = Context::MIN_CONTEXT_SLOTS + i;
Handle<Object> value = Handle<Object>(context->get(context_index), isolate);
// Reflect variables under TDZ as undefined in scope object.
- if (value->IsTheHole()) continue;
+ if (value->IsTheHole(isolate)) continue;
// This should always succeed.
// TODO(verwaest): Use AddDataProperty instead.
JSObject::SetOwnPropertyIgnoreAttributes(scope_object, name, value, NONE)
@@ -764,11 +766,11 @@
void ScopeIterator::CopyContextExtensionToScopeObject(
Handle<Context> context, Handle<JSObject> scope_object,
- KeyCollectionType type) {
+ KeyCollectionMode mode) {
if (context->extension_object() == nullptr) return;
Handle<JSObject> extension(context->extension_object());
Handle<FixedArray> keys =
- JSReceiver::GetKeys(extension, type, ENUMERABLE_STRINGS)
+ KeyAccumulator::GetKeys(extension, mode, ENUMERABLE_STRINGS)
.ToHandleChecked();
for (int i = 0; i < keys->length(); i++) {
@@ -784,6 +786,12 @@
void ScopeIterator::GetNestedScopeChain(Isolate* isolate, Scope* scope,
int position) {
+ if (scope->is_function_scope()) {
+ // Do not collect scopes of nested inner functions inside the current one.
+ Handle<JSFunction> function =
+ Handle<JSFunction>::cast(frame_inspector_->GetFunction());
+ if (scope->end_position() < function->shared()->end_position()) return;
+ }
if (scope->is_hidden()) {
// We need to add this chain element in case the scope has a context
// associated. We need to keep the scope chain and context chain in sync.
diff --git a/src/debug/debug-scopes.h b/src/debug/debug-scopes.h
index 9560227..1338e7b 100644
--- a/src/debug/debug-scopes.h
+++ b/src/debug/debug-scopes.h
@@ -153,7 +153,7 @@
Handle<JSObject> scope_object);
void CopyContextExtensionToScopeObject(Handle<Context> context,
Handle<JSObject> scope_object,
- KeyCollectionType type);
+ KeyCollectionMode mode);
// Get the chain of nested scopes within this scope for the source statement
// position. The scopes will be added to the list from the outermost scope to
diff --git a/src/debug/debug.cc b/src/debug/debug.cc
index 3b5fb5f..c69b04b 100644
--- a/src/debug/debug.cc
+++ b/src/debug/debug.cc
@@ -477,8 +477,8 @@
thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
thread_local_.last_fp_ = 0;
thread_local_.target_fp_ = 0;
- thread_local_.step_in_enabled_ = false;
thread_local_.return_value_ = Handle<Object>();
+ clear_suspended_generator();
// TODO(isolates): frames_are_dropped_?
base::NoBarrier_Store(&thread_local_.current_debug_scope_,
static_cast<base::AtomicWord>(0));
@@ -486,25 +486,24 @@
char* Debug::ArchiveDebug(char* storage) {
- char* to = storage;
- MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
+ // Simply reset state. Don't archive anything.
ThreadInit();
return storage + ArchiveSpacePerThread();
}
char* Debug::RestoreDebug(char* storage) {
- char* from = storage;
- MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
+ // Simply reset state. Don't restore anything.
+ ThreadInit();
return storage + ArchiveSpacePerThread();
}
+int Debug::ArchiveSpacePerThread() { return 0; }
-int Debug::ArchiveSpacePerThread() {
- return sizeof(ThreadLocal);
+void Debug::Iterate(ObjectVisitor* v) {
+ v->VisitPointer(&thread_local_.suspended_generator_);
}
-
DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
// Globalize the request debug info object and make it weak.
GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
@@ -537,9 +536,13 @@
// Create the debugger context.
HandleScope scope(isolate_);
ExtensionConfiguration no_extensions;
+ // TODO(yangguo): we rely on the fact that first context snapshot is usable
+ // as debug context. This dependency is gone once we remove
+ // debug context completely.
+ static const int kFirstContextSnapshotIndex = 0;
Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
- DEBUG_CONTEXT);
+ kFirstContextSnapshotIndex, DEBUG_CONTEXT);
// Fail if no context could be created.
if (context.is_null()) return false;
@@ -588,14 +591,14 @@
// Return if we failed to retrieve the debug info.
return;
}
- Handle<DebugInfo> debug_info(shared->GetDebugInfo());
+ Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
// Find the break location where execution has stopped.
BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
// Find actual break points, if any, and trigger debug break event.
Handle<Object> break_points_hit = CheckBreakPoints(&location);
- if (!break_points_hit->IsUndefined()) {
+ if (!break_points_hit->IsUndefined(isolate_)) {
// Clear all current stepping setup.
ClearStepping();
// Notify the debug event listeners.
@@ -666,7 +669,7 @@
// they are in a FixedArray.
Handle<FixedArray> break_points_hit;
int break_points_hit_count = 0;
- DCHECK(!break_point_objects->IsUndefined());
+ DCHECK(!break_point_objects->IsUndefined(isolate_));
if (break_point_objects->IsFixedArray()) {
Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
break_points_hit = factory->NewFixedArray(array->length());
@@ -714,7 +717,7 @@
Handle<Object> check_result =
CheckBreakPoints(&break_locations[i], &has_break_points);
has_break_points_at_all |= has_break_points;
- if (has_break_points && !check_result->IsUndefined()) return false;
+ if (has_break_points && !check_result->IsUndefined(isolate_)) return false;
}
return has_break_points_at_all;
}
@@ -753,7 +756,7 @@
}
// Return whether the break point is triggered.
- return result->IsTrue();
+ return result->IsTrue(isolate_);
}
@@ -795,7 +798,7 @@
// Obtain shared function info for the function.
Handle<Object> result =
FindSharedFunctionInfoInScript(script, *source_position);
- if (result->IsUndefined()) return false;
+ if (result->IsUndefined(isolate_)) return false;
// Make sure the function has set up the debug info.
Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
@@ -842,7 +845,7 @@
while (node != NULL) {
Handle<Object> result =
DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
- if (!result->IsUndefined()) {
+ if (!result->IsUndefined(isolate_)) {
// Get information in the break point.
Handle<BreakPointInfo> break_point_info =
Handle<BreakPointInfo>::cast(result);
@@ -932,14 +935,22 @@
void Debug::PrepareStepIn(Handle<JSFunction> function) {
+ CHECK(last_step_action() >= StepIn);
if (!is_active()) return;
- if (last_step_action() < StepIn) return;
if (in_debug_scope()) return;
- if (thread_local_.step_in_enabled_) {
- FloodWithOneShot(function);
- }
+ FloodWithOneShot(function);
}
+void Debug::PrepareStepInSuspendedGenerator() {
+ CHECK(has_suspended_generator());
+ if (!is_active()) return;
+ if (in_debug_scope()) return;
+ thread_local_.last_step_action_ = StepIn;
+ Handle<JSFunction> function(
+ JSGeneratorObject::cast(thread_local_.suspended_generator_)->function());
+ FloodWithOneShot(function);
+ clear_suspended_generator();
+}
void Debug::PrepareStepOnThrow() {
if (!is_active()) return;
@@ -994,10 +1005,7 @@
feature_tracker()->Track(DebugFeatureTracker::kStepping);
- // Remember this step action and count.
thread_local_.last_step_action_ = step_action;
- STATIC_ASSERT(StepFrame > StepIn);
- thread_local_.step_in_enabled_ = (step_action >= StepIn);
// If the function on the top frame is unresolved perform step out. This will
// be the case when calling unknown function and having the debugger stopped
@@ -1041,6 +1049,8 @@
debug_info->abstract_code()->SourceStatementPosition(
summary.code_offset());
thread_local_.last_fp_ = frame->UnpaddedFP();
+ // No longer perform the current async step.
+ clear_suspended_generator();
switch (step_action) {
case StepNone:
@@ -1057,11 +1067,7 @@
Deoptimizer::DeoptimizeFunction(frames_it.frame()->function());
frames_it.Advance();
}
- if (frames_it.done()) {
- // Stepping out to the embedder. Disable step-in to avoid stepping into
- // the next (unrelated) call that the embedder makes.
- thread_local_.step_in_enabled_ = false;
- } else {
+ if (!frames_it.done()) {
// Fill the caller function to return to with one-shot break points.
Handle<JSFunction> caller_function(frames_it.frame()->function());
FloodWithOneShot(caller_function);
@@ -1092,19 +1098,18 @@
Handle<SharedFunctionInfo> shared,
BreakPositionAlignment position_alignment) {
Isolate* isolate = shared->GetIsolate();
- Heap* heap = isolate->heap();
if (!shared->HasDebugInfo()) {
- return Handle<Object>(heap->undefined_value(), isolate);
+ return isolate->factory()->undefined_value();
}
Handle<DebugInfo> debug_info(shared->GetDebugInfo());
if (debug_info->GetBreakPointCount() == 0) {
- return Handle<Object>(heap->undefined_value(), isolate);
+ return isolate->factory()->undefined_value();
}
Handle<FixedArray> locations =
isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
int count = 0;
for (int i = 0; i < debug_info->break_points()->length(); ++i) {
- if (!debug_info->break_points()->get(i)->IsUndefined()) {
+ if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
BreakPointInfo* break_point_info =
BreakPointInfo::cast(debug_info->break_points()->get(i));
int break_points = break_point_info->GetBreakPointCount();
@@ -1130,7 +1135,6 @@
ClearOneShot();
thread_local_.last_step_action_ = StepNone;
- thread_local_.step_in_enabled_ = false;
thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
thread_local_.last_fp_ = 0;
thread_local_.target_fp_ = 0;
@@ -1155,12 +1159,6 @@
}
-void Debug::EnableStepIn() {
- STATIC_ASSERT(StepFrame > StepIn);
- thread_local_.step_in_enabled_ = (last_step_action() >= StepIn);
-}
-
-
bool MatchingCodeTargets(Code* target1, Code* target2) {
if (target1 == target2) return true;
if (target1->kind() != target2->kind()) return false;
@@ -1313,9 +1311,7 @@
{
SharedFunctionInfo::Iterator iterator(isolate_);
while (SharedFunctionInfo* shared = iterator.Next()) {
- if (!shared->OptimizedCodeMapIsCleared()) {
- shared->ClearOptimizedCodeMap();
- }
+ shared->ClearCodeFromOptimizedCodeMap();
}
}
@@ -1323,6 +1319,7 @@
isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
"prepare for break points");
+ DCHECK(shared->is_compiled());
bool is_interpreted = shared->HasBytecodeArray();
{
@@ -1331,7 +1328,7 @@
// smarter here and avoid the heap walk.
HeapIterator iterator(isolate_->heap());
HeapObject* obj;
- bool include_generators = !is_interpreted && shared->is_generator();
+ bool find_resumables = !is_interpreted && shared->is_resumable();
while ((obj = iterator.next())) {
if (obj->IsJSFunction()) {
@@ -1342,7 +1339,9 @@
}
if (is_interpreted) continue;
if (function->shared() == *shared) functions.Add(handle(function));
- } else if (include_generators && obj->IsJSGeneratorObject()) {
+ } else if (find_resumables && obj->IsJSGeneratorObject()) {
+ // This case handles async functions as well, as they use generator
+ // objects for in-progress async function execution.
JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj);
if (!generator_obj->is_suspended()) continue;
JSFunction* function = generator_obj->function();
@@ -1368,6 +1367,7 @@
for (Handle<JSFunction> const function : functions) {
function->ReplaceCode(shared->code());
+ JSFunction::EnsureLiterals(function);
}
for (Handle<JSGeneratorObject> const generator_obj : suspended_generators) {
@@ -1384,6 +1384,13 @@
return true;
}
+void Debug::RecordAsyncFunction(Handle<JSGeneratorObject> generator_object) {
+ if (last_step_action() <= StepOut) return;
+ if (!generator_object->function()->shared()->is_async()) return;
+ DCHECK(!has_suspended_generator());
+ thread_local_.suspended_generator_ = *generator_object;
+ ClearStepping();
+}
class SharedFunctionInfoFinder {
public:
@@ -1725,7 +1732,7 @@
HandleScope scope(isolate_);
// Check whether the promise has been marked as having triggered a message.
Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
- if (JSReceiver::GetDataProperty(promise, key)->IsUndefined()) {
+ if (JSReceiver::GetDataProperty(promise, key)->IsUndefined(isolate_)) {
OnException(value, promise);
}
}
@@ -1752,7 +1759,7 @@
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate_, has_reject_handler,
PromiseHasUserDefinedRejectHandler(jspromise), /* void */);
- uncaught = has_reject_handler->IsFalse();
+ uncaught = has_reject_handler->IsFalse(isolate_);
}
// Bail out if exception breaks are not active
if (uncaught) {
@@ -2051,7 +2058,7 @@
request_args, &maybe_exception);
if (maybe_result.ToHandle(&answer_value)) {
- if (answer_value->IsUndefined()) {
+ if (answer_value->IsUndefined(isolate_)) {
answer = isolate_->factory()->empty_string();
} else {
answer = Handle<String>::cast(answer_value);
@@ -2068,7 +2075,7 @@
isolate_, is_running, cmd_processor, 1, is_running_args);
Handle<Object> result;
if (!maybe_result.ToHandle(&result)) break;
- running = result->IsTrue();
+ running = result->IsTrue(isolate_);
} else {
Handle<Object> exception;
if (!maybe_exception.ToHandle(&exception)) break;
@@ -2102,7 +2109,7 @@
event_listener_data_ = Handle<Object>();
// Set new entry.
- if (!callback->IsUndefined() && !callback->IsNull()) {
+ if (!callback->IsUndefined(isolate_) && !callback->IsNull(isolate_)) {
event_listener_ = global_handles->Create(*callback);
if (data.is_null()) data = isolate_->factory()->undefined_value();
event_listener_data_ = global_handles->Create(*data);
@@ -2492,6 +2499,9 @@
return client_data_;
}
+v8::Isolate* EventDetailsImpl::GetIsolate() const {
+ return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
+}
CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
client_data_(NULL) {
diff --git a/src/debug/debug.h b/src/debug/debug.h
index 2cdc151..eb2708c 100644
--- a/src/debug/debug.h
+++ b/src/debug/debug.h
@@ -9,13 +9,13 @@
#include "src/arguments.h"
#include "src/assembler.h"
#include "src/base/atomicops.h"
+#include "src/base/hashmap.h"
#include "src/base/platform/platform.h"
#include "src/debug/liveedit.h"
#include "src/execution.h"
#include "src/factory.h"
#include "src/flags.h"
#include "src/frames.h"
-#include "src/hashmap.h"
#include "src/interpreter/source-position-table.h"
#include "src/runtime/runtime.h"
#include "src/string-stream.h"
@@ -38,9 +38,10 @@
StepNext = 1, // Step to the next statement in the current function.
StepIn = 2, // Step into new functions invoked or the next statement
// in the current function.
- StepFrame = 3 // Step into a new frame or return to previous frame.
-};
+ StepFrame = 3, // Step into a new frame or return to previous frame.
+ LastStepAction = StepFrame
+};
// Type of exception break. NOTE: These values are in macros.py as well.
enum ExceptionBreakType {
@@ -305,6 +306,8 @@
virtual v8::Local<v8::Context> GetEventContext() const;
virtual v8::Local<v8::Value> GetCallbackData() const;
virtual v8::Debug::ClientData* GetClientData() const;
+ virtual v8::Isolate* GetIsolate() const;
+
private:
DebugEvent event_; // Debug event causing the break.
Handle<JSObject> exec_state_; // Current execution state.
@@ -456,13 +459,15 @@
// Stepping handling.
void PrepareStep(StepAction step_action);
void PrepareStepIn(Handle<JSFunction> function);
+ void PrepareStepInSuspendedGenerator();
void PrepareStepOnThrow();
void ClearStepping();
void ClearStepOut();
- void EnableStepIn();
bool PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared);
+ void RecordAsyncFunction(Handle<JSGeneratorObject> generator_object);
+
// Returns whether the operation succeeded. Compilation can only be triggered
// if a valid closure is passed as the second argument, otherwise the shared
// function needs to be compiled already.
@@ -497,6 +502,7 @@
char* RestoreDebug(char* from);
static int ArchiveSpacePerThread();
void FreeThreadResources() { }
+ void Iterate(ObjectVisitor* v);
bool CheckExecutionState(int id) {
return is_active() && !debug_context().is_null() && break_id() != 0 &&
@@ -540,8 +546,12 @@
return reinterpret_cast<Address>(&after_break_target_);
}
- Address step_in_enabled_address() {
- return reinterpret_cast<Address>(&thread_local_.step_in_enabled_);
+ Address last_step_action_address() {
+ return reinterpret_cast<Address>(&thread_local_.last_step_action_);
+ }
+
+ Address suspended_generator_address() {
+ return reinterpret_cast<Address>(&thread_local_.suspended_generator_);
}
StepAction last_step_action() { return thread_local_.last_step_action_; }
@@ -564,6 +574,14 @@
return break_disabled_ || in_debug_event_listener_;
}
+ void clear_suspended_generator() {
+ thread_local_.suspended_generator_ = Smi::FromInt(0);
+ }
+
+ bool has_suspended_generator() const {
+ return thread_local_.suspended_generator_ != Smi::FromInt(0);
+ }
+
void OnException(Handle<Object> exception, Handle<Object> promise);
// Constructors for debug event objects.
@@ -675,11 +693,6 @@
// Frame pointer of the target frame we want to arrive at.
Address target_fp_;
- // Whether functions are flooded on entry for step-in and step-frame.
- // If we stepped out to the embedder, disable flooding to spill stepping
- // to the next call that the embedder makes.
- bool step_in_enabled_;
-
// Stores the way how LiveEdit has patched the stack. It is used when
// debugger returns control back to user script.
LiveEdit::FrameDropMode frame_drop_mode_;
@@ -687,6 +700,8 @@
// Value of accumulator in interpreter frames. In non-interpreter frames
// this value will be the hole.
Handle<Object> return_value_;
+
+ Object* suspended_generator_;
};
// Storage location for registers when handling debug break calls
diff --git a/src/debug/debug.js b/src/debug/debug.js
index 38934b0..cbd4dd2 100644
--- a/src/debug/debug.js
+++ b/src/debug/debug.js
@@ -361,7 +361,7 @@
} else {
// We might want to account columns here as well.
if (!(script.line_offset <= this.line_ &&
- this.line_ < script.line_offset + script.lineCount())) {
+ this.line_ < script.line_offset + %ScriptLineCount(script))) {
return false;
}
if (this.type_ == Debug.ScriptBreakPointType.ScriptName) {
@@ -383,11 +383,11 @@
// first piece of breakable code on the line try to find the column on the
// line which contains some source.
if (IS_UNDEFINED(column)) {
- var source_line = script.sourceLine(this.line());
+ var source_line = %ScriptSourceLine(script, line || script.line_offset);
// Allocate array for caching the columns where the actual source starts.
if (!script.sourceColumnStart_) {
- script.sourceColumnStart_ = new GlobalArray(script.lineCount());
+ script.sourceColumnStart_ = new GlobalArray(%ScriptLineCount(script));
}
// Fill cache if needed and get column where the actual source starts.
@@ -536,14 +536,14 @@
Debug.findFunctionSourceLocation = function(func, opt_line, opt_column) {
var script = %FunctionGetScript(func);
var script_offset = %FunctionGetScriptSourcePosition(func);
- return script.locationFromLine(opt_line, opt_column, script_offset);
+ return %ScriptLocationFromLine(script, opt_line, opt_column, script_offset);
};
// Returns the character position in a script based on a line number and an
// optional position within that line.
Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
- var location = script.locationFromLine(opt_line, opt_column);
+ var location = %ScriptLocationFromLine(script, opt_line, opt_column, 0);
return location ? location.position : null;
};
@@ -2085,18 +2085,34 @@
return response.failed('No source');
}
- // Get the source slice and fill it into the response.
- var slice = script.sourceSlice(from_line, to_line);
- if (!slice) {
+ var raw_script = script.value();
+
+ // Sanitize arguments and remove line offset.
+ var line_offset = raw_script.line_offset;
+ var line_count = %ScriptLineCount(raw_script);
+ from_line = IS_UNDEFINED(from_line) ? 0 : from_line - line_offset;
+ to_line = IS_UNDEFINED(to_line) ? line_count : to_line - line_offset;
+
+ if (from_line < 0) from_line = 0;
+ if (to_line > line_count) to_line = line_count;
+
+ if (from_line >= line_count || to_line < 0 || from_line > to_line) {
return response.failed('Invalid line interval');
}
+
+ // Fill in the response.
+
response.body = {};
- response.body.source = slice.sourceText();
- response.body.fromLine = slice.from_line;
- response.body.toLine = slice.to_line;
- response.body.fromPosition = slice.from_position;
- response.body.toPosition = slice.to_position;
- response.body.totalLines = script.lineCount();
+ response.body.fromLine = from_line + line_offset;
+ response.body.toLine = to_line + line_offset;
+ response.body.fromPosition = %ScriptLineStartPosition(raw_script, from_line);
+ response.body.toPosition =
+ (to_line == 0) ? 0 : %ScriptLineEndPosition(raw_script, to_line - 1);
+ response.body.totalLines = %ScriptLineCount(raw_script);
+
+ response.body.source = %_SubString(raw_script.source,
+ response.body.fromPosition,
+ response.body.toPosition);
};
diff --git a/src/debug/ia32/debug-ia32.cc b/src/debug/ia32/debug-ia32.cc
index 056407f..8e4dee7 100644
--- a/src/debug/ia32/debug-ia32.cc
+++ b/src/debug/ia32/debug-ia32.cc
@@ -38,7 +38,7 @@
void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
Handle<Code> code) {
- DCHECK_EQ(Code::BUILTIN, code->kind());
+ DCHECK(code->is_debug_stub());
static const int kSize = Assembler::kDebugBreakSlotLength;
CodePatcher patcher(isolate, pc, kSize);
diff --git a/src/debug/liveedit.cc b/src/debug/liveedit.cc
index 50d60a1..aa67537 100644
--- a/src/debug/liveedit.cc
+++ b/src/debug/liveedit.cc
@@ -621,11 +621,9 @@
this->SetSmiValueField(kParentIndexOffset_, parent_index);
}
-
-void FunctionInfoWrapper::SetFunctionCode(Handle<Code> function_code,
+void FunctionInfoWrapper::SetFunctionCode(Handle<AbstractCode> function_code,
Handle<HeapObject> code_scope_info) {
// CompileForLiveEdit must deliver full-codegen code.
- DCHECK(function_code->kind() == Code::FUNCTION);
Handle<JSValue> code_wrapper = WrapInJSValue(function_code);
this->SetField(kCodeOffset_, code_wrapper);
@@ -640,27 +638,25 @@
this->SetField(kSharedFunctionInfoOffset_, info_holder);
}
-
-Handle<Code> FunctionInfoWrapper::GetFunctionCode() {
+Handle<AbstractCode> FunctionInfoWrapper::GetFunctionCode() {
Handle<Object> element = this->GetField(kCodeOffset_);
Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element);
Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
- CHECK(raw_result->IsCode());
- return Handle<Code>::cast(raw_result);
+ CHECK(raw_result->IsAbstractCode());
+ return Handle<AbstractCode>::cast(raw_result);
}
-
-MaybeHandle<TypeFeedbackVector> FunctionInfoWrapper::GetFeedbackVector() {
+MaybeHandle<TypeFeedbackMetadata> FunctionInfoWrapper::GetFeedbackMetadata() {
Handle<Object> element = this->GetField(kSharedFunctionInfoOffset_);
if (element->IsJSValue()) {
Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element);
Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
Handle<SharedFunctionInfo> shared =
Handle<SharedFunctionInfo>::cast(raw_result);
- return Handle<TypeFeedbackVector>(shared->feedback_vector(), isolate());
+ return Handle<TypeFeedbackMetadata>(shared->feedback_metadata(), isolate());
} else {
// Scripts may never have a SharedFunctionInfo created.
- return MaybeHandle<TypeFeedbackVector>();
+ return MaybeHandle<TypeFeedbackMetadata>();
}
}
@@ -863,11 +859,11 @@
public:
static void PatchLiterals(FunctionInfoWrapper* compile_info_wrapper,
Handle<SharedFunctionInfo> shared_info,
- Isolate* isolate) {
+ bool feedback_metadata_changed, Isolate* isolate) {
int new_literal_count = compile_info_wrapper->GetLiteralCount();
int old_literal_count = shared_info->num_literals();
- if (old_literal_count == new_literal_count) {
+ if (old_literal_count == new_literal_count && !feedback_metadata_changed) {
// If literal count didn't change, simply go over all functions
// and clear literal arrays.
ClearValuesVisitor visitor;
@@ -878,10 +874,13 @@
// collect all functions and fix their literal arrays.
Handle<FixedArray> function_instances =
CollectJSFunctions(shared_info, isolate);
- Handle<TypeFeedbackVector> vector(shared_info->feedback_vector());
+ Handle<TypeFeedbackMetadata> feedback_metadata(
+ shared_info->feedback_metadata());
for (int i = 0; i < function_instances->length(); i++) {
Handle<JSFunction> fun(JSFunction::cast(function_instances->get(i)));
+ Handle<TypeFeedbackVector> vector =
+ TypeFeedbackVector::New(isolate, feedback_metadata);
Handle<LiteralsArray> new_literals =
LiteralsArray::New(isolate, vector, new_literal_count, TENURED);
fun->set_literals(*new_literals);
@@ -929,10 +928,10 @@
class ClearValuesVisitor {
public:
void visit(JSFunction* fun) {
- FixedArray* literals = fun->literals();
- int len = literals->length();
+ LiteralsArray* literals = fun->literals();
+ int len = literals->literals_count();
for (int j = 0; j < len; j++) {
- literals->set_undefined(j);
+ literals->set_literal_undefined(j);
}
}
};
@@ -1007,18 +1006,20 @@
SharedInfoWrapper shared_info_wrapper(shared_info_array);
Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
+ bool feedback_metadata_changed = false;
if (shared_info->is_compiled()) {
- Handle<Code> new_code = compile_info_wrapper.GetFunctionCode();
- Handle<Code> old_code(shared_info->code());
+ Handle<AbstractCode> new_code = compile_info_wrapper.GetFunctionCode();
if (shared_info->HasBytecodeArray()) {
- // The old code is interpreted. If we clear the bytecode array, the
- // interpreter entry trampoline will self-heal and go to compiled code.
+ DCHECK(new_code->IsBytecodeArray());
+ // The old code is interpreted, the new code must be interpreted as well.
shared_info->ClearBytecodeArray();
- shared_info->ReplaceCode(*new_code);
+ shared_info->set_bytecode_array(BytecodeArray::cast(*new_code));
} else {
+ Handle<Code> old_code(shared_info->code());
DCHECK(old_code->kind() == Code::FUNCTION);
- ReplaceCodeObject(old_code, new_code);
+ DCHECK(new_code->kind() == AbstractCode::FUNCTION);
+ ReplaceCodeObject(old_code, Handle<Code>::cast(new_code));
}
if (shared_info->HasDebugInfo()) {
// Existing break points will be re-applied. Reset the debug info here.
@@ -1031,10 +1032,14 @@
}
shared_info->DisableOptimization(kLiveEdit);
// Update the type feedback vector, if needed.
- MaybeHandle<TypeFeedbackVector> feedback_vector =
- compile_info_wrapper.GetFeedbackVector();
- if (!feedback_vector.is_null()) {
- shared_info->set_feedback_vector(*feedback_vector.ToHandleChecked());
+ MaybeHandle<TypeFeedbackMetadata> feedback_metadata =
+ compile_info_wrapper.GetFeedbackMetadata();
+ if (!feedback_metadata.is_null()) {
+ Handle<TypeFeedbackMetadata> checked_feedback_metadata =
+ feedback_metadata.ToHandleChecked();
+ feedback_metadata_changed = checked_feedback_metadata->DiffersFrom(
+ shared_info->feedback_metadata());
+ shared_info->set_feedback_metadata(*checked_feedback_metadata);
}
}
@@ -1043,7 +1048,8 @@
shared_info->set_start_position(start_position);
shared_info->set_end_position(end_position);
- LiteralFixer::PatchLiterals(&compile_info_wrapper, shared_info, isolate);
+ LiteralFixer::PatchLiterals(&compile_info_wrapper, shared_info,
+ feedback_metadata_changed, isolate);
DeoptimizeDependentFunctions(*shared_info);
isolate->compilation_cache()->Remove(shared_info);
@@ -1063,7 +1069,8 @@
Handle<Object> script_handle) {
Handle<SharedFunctionInfo> shared_info =
UnwrapSharedFunctionInfoFromJSValue(function_wrapper);
- CHECK(script_handle->IsScript() || script_handle->IsUndefined());
+ Isolate* isolate = function_wrapper->GetIsolate();
+ CHECK(script_handle->IsScript() || script_handle->IsUndefined(isolate));
SharedFunctionInfo::SetScript(shared_info, script_handle);
shared_info->DisableOptimization(kLiveEdit);
@@ -1219,18 +1226,13 @@
}
Vector<byte> buffer = buffer_writer.GetResult();
+ Handle<ByteArray> reloc_info =
+ isolate->factory()->NewByteArray(buffer.length(), TENURED);
- if (buffer.length() == code->relocation_size()) {
- // Simply patch relocation area of code.
- MemCopy(code->relocation_start(), buffer.start(), buffer.length());
- return code;
- } else {
- // Relocation info section now has different size. We cannot simply
- // rewrite it inside code object. Instead we have to create a new
- // code object.
- Handle<Code> result(isolate->factory()->CopyCode(code, buffer));
- return result;
- }
+ DisallowHeapAllocation no_gc;
+ code->set_relocation_info(*reloc_info);
+ CopyBytes(code->relocation_start(), buffer.start(), buffer.length());
+ return code;
}
void PatchPositionsInBytecodeArray(Handle<BytecodeArray> bytecode,
@@ -1248,7 +1250,8 @@
iterator.is_statement());
}
- bytecode->set_source_position_table(*builder.ToSourcePositionTable());
+ Handle<ByteArray> source_position_table = builder.ToSourcePositionTable();
+ bytecode->set_source_position_table(*source_position_table);
}
} // namespace
@@ -1601,7 +1604,7 @@
Handle<Object> new_element =
JSReceiver::GetElement(isolate, new_shared_array_, i)
.ToHandleChecked();
- if (new_element->IsUndefined()) return false;
+ if (new_element->IsUndefined(isolate)) return false;
Handle<SharedFunctionInfo> new_shared =
UnwrapSharedFunctionInfoFromJSValue(
Handle<JSValue>::cast(new_element));
@@ -1619,6 +1622,21 @@
return false;
}
+ void set_status(LiveEdit::FunctionPatchabilityStatus status) {
+ Isolate* isolate = old_shared_array_->GetIsolate();
+ int len = GetArrayLength(old_shared_array_);
+ for (int i = 0; i < len; ++i) {
+ Handle<Object> old_element =
+ JSReceiver::GetElement(isolate, result_, i).ToHandleChecked();
+ if (!old_element->IsSmi() ||
+ Smi::cast(*old_element)->value() ==
+ LiveEdit::FUNCTION_AVAILABLE_FOR_PATCH) {
+ SetElementSloppy(result_, i,
+ Handle<Smi>(Smi::FromInt(status), isolate));
+ }
+ }
+ }
+
private:
Handle<JSArray> old_shared_array_;
Handle<JSArray> new_shared_array_;
@@ -1672,7 +1690,7 @@
if (frame->is_java_script()) {
SharedFunctionInfo* shared =
JavaScriptFrame::cast(frame)->function()->shared();
- if (shared->is_generator()) {
+ if (shared->is_resumable()) {
non_droppable_frame_found = true;
non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
break;
@@ -1696,6 +1714,13 @@
// Fail.
return NULL;
}
+ if (non_droppable_reason ==
+ LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR &&
+ !target_frame_found) {
+ // Fail.
+ target.set_status(non_droppable_reason);
+ return NULL;
+ }
}
}
}
@@ -1993,7 +2018,7 @@
FunctionInfoWrapper info = FunctionInfoWrapper::cast(
*JSReceiver::GetElement(isolate_, result_, current_parent_index_)
.ToHandleChecked());
- info.SetFunctionCode(Handle<Code>(shared->code()),
+ info.SetFunctionCode(Handle<AbstractCode>(shared->abstract_code()),
Handle<HeapObject>(shared->scope_info()));
info.SetSharedFunctionInfo(shared);
diff --git a/src/debug/liveedit.h b/src/debug/liveedit.h
index af74043..32328d9 100644
--- a/src/debug/liveedit.h
+++ b/src/debug/liveedit.h
@@ -292,7 +292,7 @@
int end_position, int param_num, int literal_count,
int parent_index);
- void SetFunctionCode(Handle<Code> function_code,
+ void SetFunctionCode(Handle<AbstractCode> function_code,
Handle<HeapObject> code_scope_info);
void SetFunctionScopeInfo(Handle<Object> scope_info_array) {
@@ -309,9 +309,9 @@
return this->GetSmiValueField(kParentIndexOffset_);
}
- Handle<Code> GetFunctionCode();
+ Handle<AbstractCode> GetFunctionCode();
- MaybeHandle<TypeFeedbackVector> GetFeedbackVector();
+ MaybeHandle<TypeFeedbackMetadata> GetFeedbackMetadata();
Handle<Object> GetCodeScopeInfo();
diff --git a/src/debug/mips/debug-mips.cc b/src/debug/mips/debug-mips.cc
index 8e00d61..49320d8 100644
--- a/src/debug/mips/debug-mips.cc
+++ b/src/debug/mips/debug-mips.cc
@@ -41,7 +41,7 @@
void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
Handle<Code> code) {
- DCHECK_EQ(Code::BUILTIN, code->kind());
+ DCHECK(code->is_debug_stub());
CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions);
// Patch the code changing the debug break slot code from:
// nop(DEBUG_BREAK_NOP) - nop(1) is sll(zero_reg, zero_reg, 1)
diff --git a/src/debug/mips64/debug-mips64.cc b/src/debug/mips64/debug-mips64.cc
index aad095b..2e967d7 100644
--- a/src/debug/mips64/debug-mips64.cc
+++ b/src/debug/mips64/debug-mips64.cc
@@ -40,7 +40,7 @@
void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
Handle<Code> code) {
- DCHECK_EQ(Code::BUILTIN, code->kind());
+ DCHECK(code->is_debug_stub());
CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions);
// Patch the code changing the debug break slot code from:
// nop(DEBUG_BREAK_NOP) - nop(1) is sll(zero_reg, zero_reg, 1)
diff --git a/src/debug/mirrors.js b/src/debug/mirrors.js
index d098c1c..6f839fe 100644
--- a/src/debug/mirrors.js
+++ b/src/debug/mirrors.js
@@ -1956,7 +1956,7 @@
FrameMirror.prototype.sourceLineText = function() {
var location = this.sourceLocation();
if (location) {
- return location.sourceText();
+ return location.sourceText;
}
};
@@ -2362,7 +2362,7 @@
ScriptMirror.prototype.lineCount = function() {
- return this.script_.lineCount();
+ return %ScriptLineCount(this.script_);
};
@@ -2372,11 +2372,6 @@
};
-ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
- return this.script_.sourceSlice(opt_from_line, opt_to_line);
-};
-
-
ScriptMirror.prototype.context = function() {
return this.context_;
};
diff --git a/src/debug/ppc/OWNERS b/src/debug/ppc/OWNERS
index eb007cb..752e8e3 100644
--- a/src/debug/ppc/OWNERS
+++ b/src/debug/ppc/OWNERS
@@ -3,3 +3,4 @@
joransiu@ca.ibm.com
mbrandy@us.ibm.com
michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/debug/ppc/debug-ppc.cc b/src/debug/ppc/debug-ppc.cc
index a160bc2..7facf95 100644
--- a/src/debug/ppc/debug-ppc.cc
+++ b/src/debug/ppc/debug-ppc.cc
@@ -41,7 +41,7 @@
void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
Handle<Code> code) {
- DCHECK_EQ(Code::BUILTIN, code->kind());
+ DCHECK(code->is_debug_stub());
CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions);
// Patch the code changing the debug break slot code from
//
diff --git a/src/debug/s390/OWNERS b/src/debug/s390/OWNERS
index eb007cb..752e8e3 100644
--- a/src/debug/s390/OWNERS
+++ b/src/debug/s390/OWNERS
@@ -3,3 +3,4 @@
joransiu@ca.ibm.com
mbrandy@us.ibm.com
michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/debug/s390/debug-s390.cc b/src/debug/s390/debug-s390.cc
index c6764c2..9c33b95 100644
--- a/src/debug/s390/debug-s390.cc
+++ b/src/debug/s390/debug-s390.cc
@@ -45,7 +45,7 @@
void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
Handle<Code> code) {
- DCHECK_EQ(Code::BUILTIN, code->kind());
+ DCHECK(code->is_debug_stub());
CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength);
// Patch the code changing the debug break slot code from
//
diff --git a/src/debug/x64/debug-x64.cc b/src/debug/x64/debug-x64.cc
index a85ddb3..910d1ca 100644
--- a/src/debug/x64/debug-x64.cc
+++ b/src/debug/x64/debug-x64.cc
@@ -39,7 +39,7 @@
void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
Handle<Code> code) {
- DCHECK_EQ(Code::BUILTIN, code->kind());
+ DCHECK(code->is_debug_stub());
static const int kSize = Assembler::kDebugBreakSlotLength;
CodePatcher patcher(isolate, pc, kSize);
Label check_codesize;
diff --git a/src/debug/x87/debug-x87.cc b/src/debug/x87/debug-x87.cc
index 029a004..1cbdf45 100644
--- a/src/debug/x87/debug-x87.cc
+++ b/src/debug/x87/debug-x87.cc
@@ -38,7 +38,7 @@
void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
Handle<Code> code) {
- DCHECK_EQ(Code::BUILTIN, code->kind());
+ DCHECK(code->is_debug_stub());
static const int kSize = Assembler::kDebugBreakSlotLength;
CodePatcher patcher(isolate, pc, kSize);