Version 2.5.0
Fixed bug in cache handling of lastIndex on global regexps (issue http://crbug.com/58740).
Added USE_SIMULATOR macro that explicitly indicates that we wish to use the simulator as the execution engine (by Mark Lam <mark.lam@palm.com> from Hewlett-Packard Development Company, LP).
Fixed compilation error on ARM with gcc 4.4 (issue 894).
git-svn-id: http://v8.googlecode.com/svn/trunk@5638 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 43f4d87..e6fd607 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -447,9 +447,6 @@
void Branch(bool if_true, JumpTarget* target);
void CheckStack();
- static InlineFunctionGenerator FindInlineFunctionGenerator(
- Runtime::FunctionId function_id);
-
bool CheckForInlineRuntimeCall(CallRuntime* node);
static Handle<Code> ComputeLazyCompile(int argc);
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 9fc0c09..2855ca4 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -62,6 +62,13 @@
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
+#ifdef DEBUG
+ if (strlen(FLAG_stop_at) > 0 &&
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ __ stop("stop-at");
+ }
+#endif
+
int locals_count = scope()->num_stack_slots();
__ Push(lr, fp, cp, r1);
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 40be9bb..84d9d01 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -37,7 +37,7 @@
#include "arm/constants-arm.h"
#include "arm/simulator-arm.h"
-#if !defined(__arm__)
+#if !defined(__arm__) || defined(USE_SIMULATOR)
// Only build the simulator if not compiling for real ARM hardware.
namespace assembler {
@@ -2840,6 +2840,6 @@
} } // namespace assembler::arm
-#endif // __arm__
+#endif // !__arm__ || USE_SIMULATOR
#endif // V8_TARGET_ARCH_ARM
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index fee296e..d4c8250 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -38,7 +38,7 @@
#include "allocation.h"
-#if defined(__arm__)
+#if defined(__arm__) && !defined(USE_SIMULATOR)
// When running without a simulator we call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
@@ -70,7 +70,7 @@
reinterpret_cast<TryCatch*>(try_catch_address)
-#else // defined(__arm__)
+#else // !defined(__arm__) || defined(USE_SIMULATOR)
// When running with the simulator transition into simulated execution at this
// point.
@@ -356,6 +356,6 @@
};
-#endif // defined(__arm__)
+#endif // !defined(__arm__) || defined(USE_SIMULATOR)
#endif // V8_ARM_SIMULATOR_ARM_H_
diff --git a/src/codegen.cc b/src/codegen.cc
index 295d7b0..bda697a 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -361,24 +361,19 @@
#undef INLINE_FUNCTION_GENERATOR_ADDRESS
-CodeGenerator::InlineFunctionGenerator
- CodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
- return kInlineFunctionGenerators[
- static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
-}
-
-
bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
ZoneList<Expression*>* args = node->arguments();
Handle<String> name = node->name();
Runtime::Function* function = node->function();
if (function != NULL && function->intrinsic_type == Runtime::INLINE) {
- InlineFunctionGenerator generator =
- FindInlineFunctionGenerator(function->function_id);
- if (generator != NULL) {
- ((*this).*(generator))(args);
- return true;
- }
+ int lookup_index = static_cast<int>(function->function_id) -
+ static_cast<int>(Runtime::kFirstInlineFunction);
+ ASSERT(lookup_index >= 0);
+ ASSERT(static_cast<size_t>(lookup_index) <
+ ARRAY_SIZE(kInlineFunctionGenerators));
+ InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
+ (this->*generator)(args);
+ return true;
}
return false;
}
diff --git a/src/codegen.h b/src/codegen.h
index 2a4d9d4..8f923dd 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -62,7 +62,6 @@
// ComputeCallInitializeInLoop
// ProcessDeclarations
// DeclareGlobals
-// FindInlineRuntimeLUT
// CheckForInlineRuntimeCall
// AnalyzeCondition
// CodeForFunctionPosition
diff --git a/src/conversions.cc b/src/conversions.cc
index a7a0867..790e807 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -353,7 +353,7 @@
ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos] = '\0';
- Vector<char> buffer_vector(buffer, buffer_pos);
+ Vector<const char> buffer_vector(buffer, buffer_pos);
return sign ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
}
@@ -653,7 +653,7 @@
ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos] = '\0';
- double converted = Strtod(Vector<char>(buffer, buffer_pos), exponent);
+ double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
return sign? -converted: converted;
}
diff --git a/src/d8.js b/src/d8.js
index 5c3da13..a758e09 100644
--- a/src/d8.js
+++ b/src/d8.js
@@ -949,7 +949,7 @@
case 'suspend':
details.text = 'stopped';
break;
-
+
case 'setbreakpoint':
result = 'set breakpoint #';
result += body.breakpoint;
@@ -961,7 +961,7 @@
result += body.breakpoint;
details.text = result;
break;
-
+
case 'listbreakpoints':
result = 'breakpoints: (' + body.breakpoints.length + ')';
for (var i = 0; i < body.breakpoints.length; i++) {
diff --git a/src/date.js b/src/date.js
index b101ea6..9601470 100644
--- a/src/date.js
+++ b/src/date.js
@@ -246,7 +246,7 @@
var ltcache = {
- key: null,
+ key: null,
val: null
};
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index 34eb0f0..a0c6808 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -2118,7 +2118,7 @@
}
var script_id = request.arguments.script_id;
var preview_only = !!request.arguments.preview_only;
-
+
var scripts = %DebugGetLoadedScripts();
var the_script = null;
@@ -2139,11 +2139,11 @@
}
var new_source = request.arguments.new_source;
-
+
var result_description = Debug.LiveEdit.SetScriptSource(the_script,
new_source, preview_only, change_log);
response.body = {change_log: change_log, result: result_description};
-
+
if (!preview_only && !this.running_ && result_description.stack_modified) {
response.body.stepin_recommended = true;
}
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index ec6ad22..b072409 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -624,9 +624,6 @@
void CheckStack();
- static InlineFunctionGenerator FindInlineFunctionGenerator(
- Runtime::FunctionId function_id);
-
bool CheckForInlineRuntimeCall(CallRuntime* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index cf53f4b..150df99 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -61,6 +61,13 @@
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
+#ifdef DEBUG
+ if (strlen(FLAG_stop_at) > 0 &&
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ __ int3();
+ }
+#endif
+
__ push(ebp); // Caller's frame pointer.
__ mov(ebp, esp);
__ push(esi); // Callee's context.
diff --git a/src/liveedit-debugger.js b/src/liveedit-debugger.js
index be97989..83b703f 100644
--- a/src/liveedit-debugger.js
+++ b/src/liveedit-debugger.js
@@ -46,8 +46,7 @@
// Forward declaration for minifier.
var FunctionStatus;
-
-
+
// Applies the change to the script.
// The change is in form of list of chunks encoded in a single array as
// a series of triplets (pos1_start, pos1_end, pos2_end)
@@ -58,7 +57,7 @@
// Gather compile information about old version of script.
var old_compile_info = GatherCompileInfo(old_source, script);
-
+
// Build tree structures for old and new versions of the script.
var root_old_node = BuildCodeInfoTree(old_compile_info);
@@ -69,7 +68,7 @@
// Find all SharedFunctionInfo's that were compiled from this script.
FindLiveSharedInfos(root_old_node, script);
-
+
// Gather compile information about new version of script.
var new_compile_info;
try {
@@ -81,7 +80,7 @@
// Link recompiled script data with other data.
FindCorrespondingFunctions(root_old_node, root_new_node);
-
+
// Prepare to-do lists.
var replace_code_list = new Array();
var link_to_old_script_list = new Array();
@@ -104,7 +103,7 @@
CollectNew(node_list[i].children);
}
}
-
+
if (old_node.status == FunctionStatus.DAMAGED) {
CollectDamaged(old_node);
return;
@@ -131,17 +130,17 @@
},
updated: false
};
-
+
if (preview_only) {
return preview_description;
}
-
+
HarvestTodo(root_old_node);
-
+
// Collect shared infos for functions whose code need to be patched.
var replaced_function_infos = new Array();
for (var i = 0; i < replace_code_list.length; i++) {
- var info_wrapper = replace_code_list[i].live_shared_info_wrapper;
+ var info_wrapper = replace_code_list[i].live_shared_info_wrapper;
if (info_wrapper) {
replaced_function_infos.push(info_wrapper);
}
@@ -149,14 +148,14 @@
// We haven't changed anything before this line yet.
// Committing all changes.
-
+
// Check that function being patched is not currently on stack or drop them.
var dropped_functions_number =
CheckStackActivations(replaced_function_infos, change_log);
-
- preview_description.stack_modified = dropped_functions_number != 0;
-
- // Start with breakpoints. Convert their line/column positions and
+
+ preview_description.stack_modified = dropped_functions_number != 0;
+
+ // Start with breakpoints. Convert their line/column positions and
// temporary remove.
var break_points_restorer = TemporaryRemoveBreakPoints(script, change_log);
@@ -169,24 +168,24 @@
old_script = void 0;
} else {
var old_script_name = CreateNameForOldScript(script);
-
+
// Update the script text and create a new script representing an old
// version of the script.
old_script = %LiveEditReplaceScript(script, new_source,
old_script_name);
-
+
var link_to_old_script_report = new Array();
change_log.push( { linked_to_old_script: link_to_old_script_report } );
-
+
// We need to link to old script all former nested functions.
for (var i = 0; i < link_to_old_script_list.length; i++) {
LinkToOldScript(link_to_old_script_list[i], old_script,
link_to_old_script_report);
}
-
+
preview_description.created_script_name = old_script_name;
}
-
+
// Link to an actual script all the functions that we are going to use.
for (var i = 0; i < link_to_original_script_list.length; i++) {
%LiveEditFunctionSetScript(
@@ -196,26 +195,26 @@
for (var i = 0; i < replace_code_list.length; i++) {
PatchFunctionCode(replace_code_list[i], change_log);
}
-
+
var position_patch_report = new Array();
change_log.push( {position_patched: position_patch_report} );
-
+
for (var i = 0; i < update_positions_list.length; i++) {
// TODO(LiveEdit): take into account wether it's source_changed or
// unchanged and whether positions changed at all.
PatchPositions(update_positions_list[i], diff_array,
position_patch_report);
}
-
+
break_points_restorer(pos_translator, old_script);
-
+
preview_description.updated = true;
return preview_description;
}
// Function is public.
this.ApplyPatchMultiChunk = ApplyPatchMultiChunk;
-
+
// Fully compiles source string as a script. Returns Array of
// FunctionCompileInfo -- a descriptions of all functions of the script.
// Elements of array are ordered by start positions of functions (from top
@@ -224,7 +223,7 @@
//
// All functions get compiled linked to script provided as parameter script.
// TODO(LiveEdit): consider not using actual scripts as script, because
- // we have to manually erase all links right after compile.
+ // we have to manually erase all links right after compile.
function GatherCompileInfo(source, script) {
// Get function info, elements are partially sorted (it is a tree of
// nested functions serialized as parent followed by serialized children.
@@ -291,7 +290,7 @@
return compile_info;
}
-
+
// Replaces function's Code.
function PatchFunctionCode(old_node, change_log) {
var new_info = old_node.corresponding_node.info;
@@ -318,7 +317,7 @@
}
}
}
-
+
change_log.push( {function_patched: new_info.function_name} );
} else {
change_log.push( {function_patched: new_info.function_name,
@@ -326,7 +325,7 @@
}
}
-
+
// Makes a function associated with another instance of a script (the
// one representing its old version). This way the function still
// may access its own text.
@@ -340,12 +339,12 @@
{ name: old_info_node.info.function_name, not_found: true } );
}
}
-
+
// Returns function that restores breakpoints.
function TemporaryRemoveBreakPoints(original_script, change_log) {
var script_break_points = GetScriptBreakPoints(original_script);
-
+
var break_points_update_report = [];
change_log.push( { break_points_update: break_points_update_report } );
@@ -354,11 +353,11 @@
var break_point = script_break_points[i];
break_point.clear();
-
- // TODO(LiveEdit): be careful with resource offset here.
+
+ // TODO(LiveEdit): be careful with resource offset here.
var break_point_position = Debug.findScriptSourcePosition(original_script,
break_point.line(), break_point.column());
-
+
var old_position_description = {
position: break_point_position,
line: break_point.line(),
@@ -366,8 +365,8 @@
}
break_point_old_positions.push(old_position_description);
}
-
-
+
+
// Restores breakpoints and creates their copies in the "old" copy of
// the script.
return function (pos_translator, old_script_copy_opt) {
@@ -378,19 +377,19 @@
if (old_script_copy_opt) {
var clone = break_point.cloneForOtherScript(old_script_copy_opt);
clone.set(old_script_copy_opt);
-
+
break_points_update_report.push( {
type: "copied_to_old",
id: break_point.number(),
- new_id: clone.number(),
+ new_id: clone.number(),
positions: break_point_old_positions[i]
} );
}
-
+
var updated_position = pos_translator.Translate(
break_point_old_positions[i].position,
PosTranslator.ShiftWithTopInsideChunkHandler);
-
+
var new_location =
original_script.locationFromPosition(updated_position, false);
@@ -401,9 +400,9 @@
line: new_location.line,
column: new_location.column
}
-
+
break_point.set(original_script);
-
+
break_points_update_report.push( { type: "position_changed",
id: break_point.number(),
old_positions: break_point_old_positions[i],
@@ -413,7 +412,7 @@
}
}
-
+
function Assert(condition, message) {
if (!condition) {
if (message) {
@@ -430,7 +429,7 @@
this.len1 = len1;
this.len2 = len2;
}
-
+
function PosTranslator(diff_array) {
var chunks = new Array();
var current_diff = 0;
@@ -441,16 +440,16 @@
var pos2_end = diff_array[i + 2];
chunks.push(new DiffChunk(pos1_begin, pos2_begin, pos1_end - pos1_begin,
pos2_end - pos2_begin));
- current_diff = pos2_end - pos1_end;
+ current_diff = pos2_end - pos1_end;
}
this.chunks = chunks;
}
PosTranslator.prototype.GetChunks = function() {
return this.chunks;
}
-
+
PosTranslator.prototype.Translate = function(pos, inside_chunk_handler) {
- var array = this.chunks;
+ var array = this.chunks;
if (array.length == 0 || pos < array[0].pos1) {
return pos;
}
@@ -467,9 +466,9 @@
}
var chunk = array[chunk_index1];
if (pos >= chunk.pos1 + chunk.len1) {
- return pos + chunk.pos2 + chunk.len2 - chunk.pos1 - chunk.len1;
+ return pos + chunk.pos2 + chunk.len2 - chunk.pos1 - chunk.len1;
}
-
+
if (!inside_chunk_handler) {
inside_chunk_handler = PosTranslator.DefaultInsideChunkHandler;
}
@@ -479,17 +478,17 @@
PosTranslator.DefaultInsideChunkHandler = function(pos, diff_chunk) {
Assert(false, "Cannot translate position in changed area");
}
-
+
PosTranslator.ShiftWithTopInsideChunkHandler =
function(pos, diff_chunk) {
// We carelessly do not check whether we stay inside the chunk after
// translation.
- return pos - diff_chunk.pos1 + diff_chunk.pos2;
+ return pos - diff_chunk.pos1 + diff_chunk.pos2;
}
-
+
var FunctionStatus = {
// No change to function or its inner functions; however its positions
- // in script may have been shifted.
+ // in script may have been shifted.
UNCHANGED: "unchanged",
// The code of a function remains unchanged, but something happened inside
// some inner functions.
@@ -500,14 +499,14 @@
// Function is changed but cannot be patched.
DAMAGED: "damaged"
}
-
+
function CodeInfoTreeNode(code_info, children, array_index) {
this.info = code_info;
this.children = children;
// an index in array of compile_info
- this.array_index = array_index;
+ this.array_index = array_index;
this.parent = void 0;
-
+
this.status = FunctionStatus.UNCHANGED;
// Status explanation is used for debugging purposes and will be shown
// in user UI if some explanations are needed.
@@ -516,26 +515,26 @@
this.new_end_pos = void 0;
this.corresponding_node = void 0;
this.unmatched_new_nodes = void 0;
-
+
// 'Textual' correspondence/matching is weaker than 'pure'
// correspondence/matching. We need 'textual' level for visual presentation
// in UI, we use 'pure' level for actual code manipulation.
// Sometimes only function body is changed (functions in old and new script
// textually correspond), but we cannot patch the code, so we see them
- // as an old function deleted and new function created.
+ // as an old function deleted and new function created.
this.textual_corresponding_node = void 0;
this.textually_unmatched_new_nodes = void 0;
-
+
this.live_shared_info_wrapper = void 0;
}
-
+
// From array of function infos that is implicitly a tree creates
// an actual tree of functions in script.
function BuildCodeInfoTree(code_info_array) {
// Throughtout all function we iterate over input array.
var index = 0;
- // Recursive function that builds a branch of tree.
+ // Recursive function that builds a branch of tree.
function BuildNode() {
var my_index = index;
index++;
@@ -551,7 +550,7 @@
}
return node;
}
-
+
var root = BuildNode();
Assert(index == code_info_array.length);
return root;
@@ -570,7 +569,7 @@
this.current = function() { return chunks[chunk_index]; }
this.next = function() {
var chunk = chunks[chunk_index];
- pos_diff = chunk.pos2 + chunk.len2 - (chunk.pos1 + chunk.len1);
+ pos_diff = chunk.pos2 + chunk.len2 - (chunk.pos1 + chunk.len1);
chunk_index++;
}
this.done = function() { return chunk_index >= chunks.length; }
@@ -582,7 +581,7 @@
// below function start.
function ProcessInternals(info_node) {
info_node.new_start_pos = chunk_it.TranslatePos(
- info_node.info.start_position);
+ info_node.info.start_position);
var child_index = 0;
var code_changed = false;
var source_changed = false;
@@ -591,7 +590,7 @@
chunk_it.current().pos1 < info_node.info.end_position) {
if (child_index < info_node.children.length) {
var child = info_node.children[child_index];
-
+
if (child.info.end_position <= chunk_it.current().pos1) {
ProcessUnchangedChild(child);
child_index++;
@@ -620,7 +619,7 @@
continue;
}
} else {
- if (chunk_it.current().pos1 + chunk_it.current().len1 <=
+ if (chunk_it.current().pos1 + chunk_it.current().len1 <=
info_node.info.end_position) {
info_node.status = FunctionStatus.CHANGED;
chunk_it.next();
@@ -645,14 +644,14 @@
info_node.status = FunctionStatus.SOURCE_CHANGED;
}
info_node.new_end_pos =
- chunk_it.TranslatePos(info_node.info.end_position);
+ chunk_it.TranslatePos(info_node.info.end_position);
}
-
+
function ProcessUnchangedChild(node) {
node.new_start_pos = chunk_it.TranslatePos(node.info.start_position);
node.new_end_pos = chunk_it.TranslatePos(node.info.end_position);
}
-
+
ProcessInternals(code_info_tree);
}
@@ -670,7 +669,7 @@
function ProcessChildren(old_node, new_node) {
var old_children = old_node.children;
var new_children = new_node.children;
-
+
var unmatched_new_nodes_list = [];
var textually_unmatched_new_nodes_list = [];
@@ -728,13 +727,13 @@
old_index++;
}
}
-
+
while (new_index < new_children.length) {
unmatched_new_nodes_list.push(new_children[new_index]);
textually_unmatched_new_nodes_list.push(new_children[new_index]);
new_index++;
}
-
+
if (old_node.status == FunctionStatus.CHANGED) {
var why_wrong_expectations =
WhyFunctionExpectationsDiffer(old_node.info, new_node.info);
@@ -749,23 +748,23 @@
}
ProcessChildren(old_code_tree, new_code_tree);
-
+
old_code_tree.corresponding_node = new_code_tree;
old_code_tree.textual_corresponding_node = new_code_tree;
Assert(old_code_tree.status != FunctionStatus.DAMAGED,
"Script became damaged");
}
-
+
function FindLiveSharedInfos(old_code_tree, script) {
var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script);
-
+
var shared_infos = new Array();
-
+
for (var i = 0; i < shared_raw_list.length; i++) {
shared_infos.push(new SharedInfoWrapper(shared_raw_list[i]));
}
-
+
// Finds SharedFunctionInfo that corresponds compile info with index
// in old version of the script.
function FindFunctionInfo(compile_info) {
@@ -777,7 +776,7 @@
}
}
}
-
+
function TraverseTree(node) {
var info_wrapper = FindFunctionInfo(node.info);
if (info_wrapper) {
@@ -791,7 +790,7 @@
TraverseTree(old_code_tree);
}
-
+
// An object describing function compilation details. Its index fields
// apply to indexes inside array that stores these objects.
function FunctionCompileInfo(raw_array) {
@@ -807,7 +806,7 @@
this.next_sibling_index = null;
this.raw_array = raw_array;
}
-
+
function SharedInfoWrapper(raw_array) {
this.function_name = raw_array[0];
this.start_position = raw_array[1];
@@ -821,7 +820,7 @@
var shared_info_wrapper = old_info_node.live_shared_info_wrapper;
if (!shared_info_wrapper) {
// TODO(LiveEdit): function is not compiled yet or is already collected.
- report_array.push(
+ report_array.push(
{ name: old_info_node.info.function_name, info_not_found: true } );
return;
}
@@ -835,44 +834,44 @@
// TODO(635): try better than this; support several changes.
return script.name + " (old)";
}
-
+
// Compares a function interface old and new version, whether it
// changed or not. Returns explanation if they differ.
function WhyFunctionExpectationsDiffer(function_info1, function_info2) {
// Check that function has the same number of parameters (there may exist
// an adapter, that won't survive function parameter number change).
if (function_info1.param_num != function_info2.param_num) {
- return "Changed parameter number: " + function_info1.param_num +
+ return "Changed parameter number: " + function_info1.param_num +
" and " + function_info2.param_num;
}
var scope_info1 = function_info1.scope_info;
var scope_info2 = function_info2.scope_info;
- var scope_info1_text;
- var scope_info2_text;
-
+ var scope_info1_text;
+ var scope_info2_text;
+
if (scope_info1) {
- scope_info1_text = scope_info1.toString();
+ scope_info1_text = scope_info1.toString();
} else {
scope_info1_text = "";
}
if (scope_info2) {
- scope_info2_text = scope_info2.toString();
+ scope_info2_text = scope_info2.toString();
} else {
scope_info2_text = "";
}
-
+
if (scope_info1_text != scope_info2_text) {
return "Incompatible variable maps: [" + scope_info1_text +
- "] and [" + scope_info2_text + "]";
+ "] and [" + scope_info2_text + "]";
}
// No differences. Return undefined.
return;
}
-
+
// Minifier forward declaration.
var FunctionPatchabilityStatus;
-
+
// For array of wrapped shared function infos checks that none of them
// have activations on stack (of any thread). Throws a Failure exception
// if this proves to be false.
@@ -886,7 +885,7 @@
// Extra array element may contain error message.
throw new Failure(result[shared_list.length]);
}
-
+
var problems = new Array();
var dropped = new Array();
for (var i = 0; i < shared_list.length; i++) {
@@ -896,7 +895,7 @@
} else if (result[i] != FunctionPatchabilityStatus.AVAILABLE_FOR_PATCH) {
var description = {
name: shared.function_name,
- start_pos: shared.start_position,
+ start_pos: shared.start_position,
end_pos: shared.end_position,
replace_problem:
FunctionPatchabilityStatus.SymbolName(result[i])
@@ -911,10 +910,10 @@
change_log.push( { functions_on_stack: problems } );
throw new Failure("Blocked by functions on stack");
}
-
+
return dropped.length;
}
-
+
// A copy of the FunctionPatchabilityStatus enum from liveedit.h
var FunctionPatchabilityStatus = {
AVAILABLE_FOR_PATCH: 1,
@@ -923,17 +922,17 @@
BLOCKED_UNDER_NATIVE_CODE: 4,
REPLACED_ON_ACTIVE_STACK: 5
}
-
+
FunctionPatchabilityStatus.SymbolName = function(code) {
var enum = FunctionPatchabilityStatus;
for (name in enum) {
if (enum[name] == code) {
return name;
}
- }
+ }
}
-
-
+
+
// A logical failure in liveedit process. This means that change_log
// is valid and consistent description of what happened.
function Failure(message) {
@@ -941,11 +940,11 @@
}
// Function (constructor) is public.
this.Failure = Failure;
-
+
Failure.prototype.toString = function() {
return "LiveEdit Failure: " + this.message;
}
-
+
// A testing entry.
function GetPcFromSourcePos(func, source_pos) {
return %GetFunctionCodePositionFromSource(func, source_pos);
@@ -962,7 +961,7 @@
}
// Function is public.
this.SetScriptSource = SetScriptSource;
-
+
function CompareStringsLinewise(s1, s2) {
return %LiveEditCompareStringsLinewise(s1, s2);
}
@@ -978,19 +977,19 @@
function ApplySingleChunkPatch(script, change_pos, change_len, new_str,
change_log) {
var old_source = script.source;
-
+
// Prepare new source string.
var new_source = old_source.substring(0, change_pos) +
new_str + old_source.substring(change_pos + change_len);
-
+
return ApplyPatchMultiChunk(script,
[ change_pos, change_pos + change_len, change_pos + new_str.length],
new_source, false, change_log);
}
-
+
// Creates JSON description for a change tree.
function DescribeChangeTree(old_code_tree) {
-
+
function ProcessOldNode(node) {
var child_infos = [];
for (var i = 0; i < node.children.length; i++) {
@@ -1011,7 +1010,7 @@
positions: DescribePositions(node),
status: node.status,
children: child_infos,
- new_children: new_child_infos
+ new_children: new_child_infos
};
if (node.status_explanation) {
res.status_explanation = node.status_explanation;
@@ -1021,7 +1020,7 @@
}
return res;
}
-
+
function ProcessNewNode(node) {
var child_infos = [];
// Do not list ancestors.
@@ -1037,18 +1036,18 @@
};
return res;
}
-
+
function DescribePositions(node) {
return {
start_position: node.info.start_position,
end_position: node.info.end_position
};
}
-
+
return ProcessOldNode(old_code_tree);
}
-
+
// Functions are public for tests.
this.TestApi = {
PosTranslator: PosTranslator,
diff --git a/src/messages.js b/src/messages.js
index 4f492bc..7f9c0f8 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -438,18 +438,18 @@
/**
* Returns the name of script if available, contents of sourceURL comment
- * otherwise. See
+ * otherwise. See
* http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
* for details on using //@ sourceURL comment to identify scritps that don't
* have name.
- *
+ *
* @return {?string} script name if present, value for //@ sourceURL comment
* otherwise.
*/
Script.prototype.nameOrSourceURL = function() {
if (this.name)
return this.name;
- // TODO(608): the spaces in a regexp below had to be escaped as \040
+ // TODO(608): the spaces in a regexp below had to be escaped as \040
// because this file is being processed by js2c whose handling of spaces
// in regexps is broken. Also, ['"] are excluded from allowed URLs to
// avoid matches against sources that invoke evals with sourceURL.
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index 57bed6a..59a5373 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -39,7 +39,7 @@
namespace v8i = v8::internal;
-#if !defined(__mips)
+#if !defined(__mips) || defined(USE_SIMULATOR)
// Only build the simulator if not compiling for real MIPS hardware.
namespace assembler {
@@ -1645,6 +1645,6 @@
} } // namespace assembler::mips
-#endif // __mips
+#endif // !__mips || USE_SIMULATOR
#endif // V8_TARGET_ARCH_MIPS
diff --git a/src/mips/simulator-mips.h b/src/mips/simulator-mips.h
index d5dfc30..6e42683 100644
--- a/src/mips/simulator-mips.h
+++ b/src/mips/simulator-mips.h
@@ -38,7 +38,7 @@
#include "allocation.h"
-#if defined(__mips)
+#if defined(__mips) && !defined(USE_SIMULATOR)
// When running without a simulator we call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
@@ -79,7 +79,7 @@
reinterpret_cast<TryCatch*>(try_catch_address)
-#else // #if defined(__mips)
+#else // #if !defined(__mips) || defined(USE_SIMULATOR)
// When running with the simulator transition into simulated execution at this
// point.
@@ -305,7 +305,7 @@
}
};
-#endif // defined(__mips)
+#endif // !defined(__mips) || defined(USE_SIMULATOR)
#endif // V8_MIPS_SIMULATOR_MIPS_H_
diff --git a/src/mirror-debugger.js b/src/mirror-debugger.js
index 761b9b3..6b9e965 100644
--- a/src/mirror-debugger.js
+++ b/src/mirror-debugger.js
@@ -1611,7 +1611,7 @@
result += ' returning ';
result += this.returnValue().toText();
}
-
+
return result;
}
diff --git a/src/objects.cc b/src/objects.cc
index 883d789..59ed1de 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1180,7 +1180,11 @@
if (map()->constructor()->IsJSFunction()) {
JSFunction* constructor = JSFunction::cast(map()->constructor());
String* name = String::cast(constructor->shared()->name());
- return name->length() > 0 ? name : constructor->shared()->inferred_name();
+ if (name->length() > 0) return name;
+ String* inferred_name = constructor->shared()->inferred_name();
+ if (inferred_name->length() > 0) return inferred_name;
+ Object* proto = GetPrototype();
+ if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
}
// If the constructor is not present, return "Object".
return Heap::Object_symbol();
@@ -6473,7 +6477,7 @@
// When we set the is_extensible flag to false we always force
// the element into dictionary mode (and force them to stay there).
if (!map()->is_extensible()) {
- Handle<Object> number(Heap::NumberFromUint32(index));
+ Handle<Object> number(Factory::NewNumberFromUint(index));
Handle<String> index_string(Factory::NumberToString(number));
Handle<Object> args[1] = { index_string };
return Top::Throw(*Factory::NewTypeError("object_not_extensible",
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 08ee046..977c67c 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -94,12 +94,18 @@
}
+static void DeleteIndexName(char** name_ptr) {
+ DeleteArray(*name_ptr);
+}
+
+
StringsStorage::~StringsStorage() {
for (HashMap::Entry* p = names_.Start();
p != NULL;
p = names_.Next(p)) {
DeleteArray(reinterpret_cast<const char*>(p->value));
}
+ index_names_.Iterate(DeleteIndexName);
}
@@ -120,6 +126,22 @@
}
+const char* StringsStorage::GetName(int index) {
+ ASSERT(index >= 0);
+ if (index_names_.length() <= index) {
+ index_names_.AddBlock(
+ NULL, index - index_names_.length() + 1);
+ }
+ if (index_names_[index] == NULL) {
+ const int kMaximumNameLength = 32;
+ char* name = NewArray<char>(kMaximumNameLength);
+ OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", index);
+ index_names_[index] = name;
+ }
+ return index_names_[index];
+}
+
+
const char* CodeEntry::kEmptyNamePrefix = "";
@@ -485,11 +507,6 @@
}
-static void DeleteArgsCountName(char** name_ptr) {
- DeleteArray(*name_ptr);
-}
-
-
static void DeleteCodeEntry(CodeEntry** entry_ptr) {
delete *entry_ptr;
}
@@ -508,7 +525,6 @@
current_profiles_.Iterate(DeleteCpuProfile);
profiles_by_token_.Iterate(DeleteProfilesList);
code_entries_.Iterate(DeleteCodeEntry);
- args_count_names_.Iterate(DeleteArgsCountName);
}
@@ -706,22 +722,6 @@
}
-const char* CpuProfilesCollection::GetName(int args_count) {
- ASSERT(args_count >= 0);
- if (args_count_names_.length() <= args_count) {
- args_count_names_.AddBlock(
- NULL, args_count - args_count_names_.length() + 1);
- }
- if (args_count_names_[args_count] == NULL) {
- const int kMaximumNameLength = 32;
- char* name = NewArray<char>(kMaximumNameLength);
- OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", args_count);
- args_count_names_[args_count] = name;
- }
- return args_count_names_[args_count];
-}
-
-
void CpuProfilesCollection::AddPathToCurrentProfiles(
const Vector<CodeEntry*>& path) {
// As starting / stopping profiles is rare relatively to this
@@ -1001,6 +1001,8 @@
case kString: return "/string/";
case kCode: return "/code/";
case kArray: return "/array/";
+ case kRegExp: return "/regexp/";
+ case kHeapNumber: return "/number/";
default: return "???";
}
}
@@ -1284,11 +1286,16 @@
} else if (object->IsJSFunction()) {
JSFunction* func = JSFunction::cast(object);
SharedFunctionInfo* shared = func->shared();
- String* name = String::cast(shared->name())->length() > 0 ?
- String::cast(shared->name()) : shared->inferred_name();
return AddEntry(object,
HeapEntry::kClosure,
- collection_->GetFunctionName(name),
+ collection_->GetName(String::cast(shared->name())),
+ children_count,
+ retainers_count);
+ } else if (object->IsJSRegExp()) {
+ JSRegExp* re = JSRegExp::cast(object);
+ return AddEntry(object,
+ HeapEntry::kRegExp,
+ collection_->GetName(re->Pattern()),
children_count,
retainers_count);
} else if (object->IsJSObject()) {
@@ -1333,6 +1340,12 @@
"",
children_count,
retainers_count);
+ } else if (object->IsHeapNumber()) {
+ return AddEntry(object,
+ HeapEntry::kHeapNumber,
+ "number",
+ children_count,
+ retainers_count);
}
// No interest in this object.
return NULL;
@@ -1342,12 +1355,14 @@
bool HeapSnapshot::WillAddEntry(HeapObject* object) {
return object == kInternalRootObject
|| object->IsJSFunction()
+ || object->IsJSRegExp()
|| object->IsJSObject()
|| object->IsString()
|| object->IsCode()
|| object->IsSharedFunctionInfo()
|| object->IsScript()
- || object->IsFixedArray();
+ || object->IsFixedArray()
+ || object->IsHeapNumber();
}
@@ -1904,13 +1919,21 @@
ExtractClosureReferences(js_obj, entry);
ExtractPropertyReferences(js_obj, entry);
ExtractElementReferences(js_obj, entry);
+ ExtractInternalReferences(js_obj, entry);
SetPropertyReference(
- obj, entry, Heap::prototype_symbol(), js_obj->map()->prototype());
+ obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype());
+ if (obj->IsJSFunction()) {
+ JSFunction* js_fun = JSFunction::cast(obj);
+ if (js_fun->has_prototype()) {
+ SetPropertyReference(
+ obj, entry, Heap::prototype_symbol(), js_fun->prototype());
+ }
+ }
} else if (obj->IsString()) {
if (obj->IsConsString()) {
ConsString* cs = ConsString::cast(obj);
- SetElementReference(obj, entry, 0, cs->first());
- SetElementReference(obj, entry, 1, cs->second());
+ SetInternalReference(obj, entry, "1", cs->first());
+ SetInternalReference(obj, entry, "2", cs->second());
}
} else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
IndexedReferencesExtractor refs_extractor(this, obj, entry);
@@ -2005,6 +2028,16 @@
}
+void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj,
+ HeapEntry* entry) {
+ int length = js_obj->GetInternalFieldCount();
+ for (int i = 0; i < length; ++i) {
+ Object* o = js_obj->GetInternalField(i);
+ SetInternalReference(js_obj, entry, i, o);
+ }
+}
+
+
void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
String* reference_name,
@@ -2049,13 +2082,31 @@
}
+void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
+ HeapEntry* parent_entry,
+ int index,
+ Object* child_obj) {
+ HeapEntry* child_entry = GetEntry(child_obj);
+ if (child_entry != NULL) {
+ filler_->SetNamedReference(HeapGraphEdge::kInternal,
+ parent_obj,
+ parent_entry,
+ collection_->GetName(index),
+ child_obj,
+ child_entry);
+ }
+}
+
+
void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
String* reference_name,
Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
- filler_->SetNamedReference(HeapGraphEdge::kProperty,
+ HeapGraphEdge::Type type = reference_name->length() > 0 ?
+ HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
+ filler_->SetNamedReference(type,
parent_obj,
parent_entry,
collection_->GetName(reference_name),
@@ -2351,7 +2402,9 @@
"," JSON_S("string")
"," JSON_S("object")
"," JSON_S("code")
- "," JSON_S("closure"))
+ "," JSON_S("closure")
+ "," JSON_S("regexp")
+ "," JSON_S("number"))
"," JSON_S("string")
"," JSON_S("number")
"," JSON_S("number")
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 4206d29..6f63f6a 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -67,6 +67,7 @@
~StringsStorage();
const char* GetName(String* name);
+ const char* GetName(int index);
inline const char* GetFunctionName(String* name);
inline const char* GetFunctionName(const char* name);
@@ -78,6 +79,8 @@
// Mapping of strings by String::Hash to const char* strings.
HashMap names_;
+ // Mapping from ints to char* strings.
+ List<char*> index_names_;
DISALLOW_COPY_AND_ASSIGN(StringsStorage);
};
@@ -284,6 +287,9 @@
const char* GetName(String* name) {
return function_and_resource_names_.GetName(name);
}
+ const char* GetName(int args_count) {
+ return function_and_resource_names_.GetName(args_count);
+ }
CpuProfile* GetProfile(int security_token_id, unsigned uid);
bool IsLastProfile(const char* title);
@@ -302,7 +308,6 @@
static const int kMaxSimultaneousProfiles = 100;
private:
- const char* GetName(int args_count);
const char* GetFunctionName(String* name) {
return function_and_resource_names_.GetFunctionName(name);
}
@@ -317,8 +322,6 @@
}
StringsStorage function_and_resource_names_;
- // Mapping from args_count (int) to char* strings.
- List<char*> args_count_names_;
List<CodeEntry*> code_entries_;
List<List<CpuProfile*>* > profiles_by_token_;
// Mapping from profiles' uids to indexes in the second nested list
@@ -502,7 +505,9 @@
kString = v8::HeapGraphNode::kString,
kObject = v8::HeapGraphNode::kObject,
kCode = v8::HeapGraphNode::kCode,
- kClosure = v8::HeapGraphNode::kClosure
+ kClosure = v8::HeapGraphNode::kClosure,
+ kRegExp = v8::HeapGraphNode::kRegExp,
+ kHeapNumber = v8::HeapGraphNode::kHeapNumber
};
HeapEntry() { }
@@ -824,6 +829,7 @@
HeapSnapshot* GetSnapshot(unsigned uid);
const char* GetName(String* name) { return names_.GetName(name); }
+ const char* GetName(int index) { return names_.GetName(index); }
const char* GetFunctionName(String* name) {
return names_.GetFunctionName(name);
}
@@ -948,6 +954,7 @@
void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry);
void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry);
void ExtractElementReferences(JSObject* js_obj, HeapEntry* entry);
+ void ExtractInternalReferences(JSObject* js_obj, HeapEntry* entry);
void SetClosureReference(HeapObject* parent_obj,
HeapEntry* parent,
String* reference_name,
@@ -960,6 +967,10 @@
HeapEntry* parent,
const char* reference_name,
Object* child);
+ void SetInternalReference(HeapObject* parent_obj,
+ HeapEntry* parent,
+ int index,
+ Object* child);
void SetPropertyReference(HeapObject* parent_obj,
HeapEntry* parent,
String* reference_name,
diff --git a/src/regexp.js b/src/regexp.js
index faa525d..51f4b09 100644
--- a/src/regexp.js
+++ b/src/regexp.js
@@ -126,11 +126,11 @@
this.regExp = 0;
this.subject = 0;
this.replaceString = 0;
- this.lastIndex = 0; // Also used for splitLimit when type is "split"
this.answer = 0;
// answerSaved marks whether the contents of answer is valid for a cache
// hit in RegExpExec, StringMatch and StringSplit.
this.answerSaved = false;
+ this.splitLimit = 0; // Used only when type is "split".
}
@@ -181,22 +181,30 @@
var cache = regExpCache;
var saveAnswer = false;
+ var lastIndex = this.lastIndex;
+
+ // Since cache.subject is always a string, a matching input can not
+ // cause visible side-effects when converted to a string, so we can omit
+ // the conversion required by the specification.
+ // Likewise, the regexp.lastIndex and regexp.global properties are value
+ // properties that are not configurable, so reading them can also not cause
+ // any side effects (converting lastIndex to a number can, though).
if (%_ObjectEquals(cache.type, 'exec') &&
- %_ObjectEquals(cache.lastIndex, this.lastIndex) &&
+ %_ObjectEquals(0, lastIndex) &&
%_IsRegExpEquivalent(cache.regExp, this) &&
%_ObjectEquals(cache.subject, string)) {
if (cache.answerSaved) {
- // If this regexp is not global, cache.lastIndex is zero, so we only get
- // here if this.lastIndex is zero, and resulting this.lastIndex
- // must be zero too, so no change is necessary.
- if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
+ // The regexp.lastIndex value must be 0 for non-global RegExps, and for
+ // global RegExps we only cache negative results, which gives a lastIndex
+ // of zero as well.
+ this.lastIndex = 0;
return %_RegExpCloneResult(cache.answer);
} else {
saveAnswer = true;
}
}
- if (%_ArgumentsLength() == 0) {
+ if (%_ArgumentsLength() === 0) {
var regExpInput = LAST_INPUT(lastMatchInfo);
if (IS_UNDEFINED(regExpInput)) {
throw MakeError('no_input_to_regexp', [this]);
@@ -209,41 +217,48 @@
} else {
s = ToString(string);
}
- var lastIndex = this.lastIndex;
+ var global = this.global;
- var i = this.global ? TO_INTEGER(lastIndex) : 0;
-
- if (i < 0 || i > s.length) {
- this.lastIndex = 0;
- return null;
+ // Conversion is required by the ES5 specification (RegExp.prototype.exec
+ // algorithm, step 5) even if the value is discarded for non-global RegExps.
+ var i = TO_INTEGER(lastIndex);
+ if (global) {
+ if (i < 0 || i > s.length) {
+ this.lastIndex = 0;
+ return null;
+ }
+ } else {
+ i = 0;
}
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
// matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
- if (matchIndices == null) {
- if (this.global) {
+ if (matchIndices === null) {
+ if (global) {
+ // Cache negative result only if initial lastIndex was zero.
this.lastIndex = 0;
- if (lastIndex != 0) return matchIndices;
+ if (lastIndex !== 0) return matchIndices;
}
- cache.lastIndex = lastIndex;
cache.regExp = this;
- cache.subject = s;
- cache.answer = matchIndices; // Null.
+ cache.subject = s; // Always a string.
+ cache.answer = null;
cache.answerSaved = true; // Safe since no cloning is needed.
cache.type = 'exec';
return matchIndices; // No match.
}
+
+ // Successful match.
lastMatchInfoOverride = null;
var result = BuildResultFromMatchInfo(matchIndices, s);
- if (this.global) {
+ if (global) {
+ // Don't cache positive results for global regexps.
this.lastIndex = lastMatchInfo[CAPTURE1];
} else {
cache.regExp = this;
cache.subject = s;
- cache.lastIndex = lastIndex;
if (saveAnswer) cache.answer = %_RegExpCloneResult(result);
cache.answerSaved = saveAnswer;
cache.type = 'exec';
@@ -273,32 +288,49 @@
}
string = regExpInput;
}
+
+ var lastIndex = this.lastIndex;
+
+ var cache = regExpCache;
+ if (%_ObjectEquals(cache.type, 'test') &&
+ %_IsRegExpEquivalent(cache.regExp, this) &&
+ %_ObjectEquals(cache.subject, string) &&
+ %_ObjectEquals(0, lastIndex)) {
+ // The regexp.lastIndex value must be 0 for non-global RegExps, and for
+ // global RegExps we only cache negative results, which gives a resulting
+ // lastIndex of zero as well.
+ if (global) this.lastIndex = 0;
+ return cache.answer;
+ }
+
var s;
if (IS_STRING(string)) {
s = string;
} else {
s = ToString(string);
}
+ var length = s.length;
- var lastIndex = this.lastIndex;
- var cache = regExpCache;
- if (%_ObjectEquals(cache.type, 'test') &&
- %_IsRegExpEquivalent(cache.regExp, this) &&
- %_ObjectEquals(cache.subject, string) &&
- %_ObjectEquals(cache.lastIndex, lastIndex)) {
- // If this regexp is not global, cache.lastIndex is zero, so we only get
- // here if this.lastIndex is zero, and resulting this.lastIndex
- // must be zero too, so no change is necessary.
- if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
- return cache.answer;
+ // Conversion is required by the ES5 specification (RegExp.prototype.exec
+ // algorithm, step 5) even if the value is discarded for non-global RegExps.
+ var i = TO_INTEGER(lastIndex);
+ if (global) {
+ if (i < 0 || i > length) {
+ this.lastIndex = 0;
+ return false;
+ }
+ } else {
+ i = 0;
}
+ var global = this.global;
+
// Remove irrelevant preceeding '.*' in a test regexp. The expression
// checks whether this.source starts with '.*' and that the third
// char is not a '?'
- if (%_StringCharCodeAt(this.source,0) == 46 && // '.'
- %_StringCharCodeAt(this.source,1) == 42 && // '*'
- %_StringCharCodeAt(this.source,2) != 63) { // '?'
+ if (%_StringCharCodeAt(this.source, 0) == 46 && // '.'
+ %_StringCharCodeAt(this.source, 1) == 42 && // '*'
+ %_StringCharCodeAt(this.source, 2) != 63) { // '?'
if (!%_ObjectEquals(regexp_key, this)) {
regexp_key = this;
regexp_val = new $RegExp(this.source.substring(2, this.source.length),
@@ -309,33 +341,28 @@
if (!regexp_val.test(s)) return false;
}
- var length = s.length;
- var i = this.global ? TO_INTEGER(lastIndex) : 0;
-
- cache.type = 'test';
- cache.regExp = this;
- cache.subject = s;
- cache.lastIndex = i;
-
- if (i < 0 || i > length) {
- this.lastIndex = 0;
- cache.answer = false;
- return false;
- }
-
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
// matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
- if (matchIndices == null) {
- if (this.global) this.lastIndex = 0;
- cache.answer = false;
- return false;
+ var result = (matchIndices !== null);
+ if (result) {
+ lastMatchInfoOverride = null;
}
- lastMatchInfoOverride = null;
- if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
- cache.answer = true;
- return true;
+ if (global) {
+ if (result) {
+ this.lastIndex = lastMatchInfo[CAPTURE1];
+ return true;
+ } else {
+ this.lastIndex = 0;
+ if (lastIndex !== 0) return false;
+ }
+ }
+ cache.type = 'test';
+ cache.regExp = this;
+ cache.subject = s;
+ cache.answer = result;
+ return result;
}
@@ -345,12 +372,9 @@
// ecma_2/RegExp/properties-001.js.
var src = this.source ? this.source : '(?:)';
var result = '/' + src + '/';
- if (this.global)
- result += 'g';
- if (this.ignoreCase)
- result += 'i';
- if (this.multiline)
- result += 'm';
+ if (this.global) result += 'g';
+ if (this.ignoreCase) result += 'i';
+ if (this.multiline) result += 'm';
return result;
}
diff --git a/src/string.js b/src/string.js
index 30eedb3..d97f632 100644
--- a/src/string.js
+++ b/src/string.js
@@ -611,7 +611,7 @@
if (%_ObjectEquals(cache.type, 'split') &&
%_IsRegExpEquivalent(cache.regExp, separator) &&
%_ObjectEquals(cache.subject, subject) &&
- %_ObjectEquals(cache.lastIndex, limit)) {
+ %_ObjectEquals(cache.splitLimit, limit)) {
if (cache.answerSaved) {
return CloneDenseArray(cache.answer);
} else {
@@ -622,8 +622,7 @@
cache.type = 'split';
cache.regExp = separator;
cache.subject = subject;
- // Reuse lastIndex field for split limit when type is "split".
- cache.lastIndex = limit;
+ cache.splitLimit = limit;
%_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
diff --git a/src/strtod.cc b/src/strtod.cc
index bfbb5db..68444fc 100644
--- a/src/strtod.cc
+++ b/src/strtod.cc
@@ -43,6 +43,14 @@
// 2^64 = 18446744073709551616
// Any integer with at most 19 digits will hence fit into a 64bit datatype.
static const int kMaxUint64DecimalDigits = 19;
+// Max double: 1.7976931348623157 x 10^308
+// Min non-zero double: 4.9406564584124654 x 10^-324
+// Any x >= 10^309 is interpreted as +infinity.
+// Any x <= 10^-324 is interpreted as 0.
+// Note that 2.5e-324 (despite being smaller than the min double) will be read
+// as non-zero (equal to the min non-zero double).
+static const int kMaxDecimalPower = 309;
+static const int kMinDecimalPower = -324;
static const double exact_powers_of_ten[] = {
1.0, // 10^0
@@ -76,26 +84,50 @@
extern "C" double gay_strtod(const char* s00, const char** se);
-static double old_strtod(Vector<char> buffer, int exponent) {
+static double old_strtod(Vector<const char> buffer, int exponent) {
char gay_buffer[1024];
Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer));
- buffer.start()[buffer.length()] = '\0';
- OS::SNPrintF(gay_buffer_vector, "%se%d", buffer.start(), exponent);
+ int pos = 0;
+ for (int i = 0; i < buffer.length(); ++i) {
+ gay_buffer_vector[pos++] = buffer[i];
+ }
+ gay_buffer_vector[pos++] = 'e';
+ if (exponent < 0) {
+ gay_buffer_vector[pos++] = '-';
+ exponent = -exponent;
+ }
+ const int kNumberOfExponentDigits = 5;
+ for (int i = kNumberOfExponentDigits - 1; i >= 0; i--) {
+ gay_buffer_vector[pos + i] = exponent % 10 + '0';
+ exponent /= 10;
+ }
+ pos += kNumberOfExponentDigits;
+ gay_buffer_vector[pos] = '\0';
return gay_strtod(gay_buffer, NULL);
}
-static Vector<char> TrimTrailingZeros(Vector<char> buffer) {
- for (int i = buffer.length() - 1; i >= 0; --i) {
+static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
+ for (int i = 0; i < buffer.length(); i++) {
if (buffer[i] != '0') {
- return Vector<char>(buffer.start(), i + 1);
+ return Vector<const char>(buffer.start() + i, buffer.length() - i);
}
}
- return Vector<char>(buffer.start(), 0);
+ return Vector<const char>(buffer.start(), 0);
}
-uint64_t ReadUint64(Vector<char> buffer) {
+static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
+ for (int i = buffer.length() - 1; i >= 0; --i) {
+ if (buffer[i] != '0') {
+ return Vector<const char>(buffer.start(), i + 1);
+ }
+ }
+ return Vector<const char>(buffer.start(), 0);
+}
+
+
+uint64_t ReadUint64(Vector<const char> buffer) {
ASSERT(buffer.length() <= kMaxUint64DecimalDigits);
uint64_t result = 0;
for (int i = 0; i < buffer.length(); ++i) {
@@ -107,10 +139,13 @@
}
-double Strtod(Vector<char> buffer, int exponent) {
- Vector<char> trimmed = TrimTrailingZeros(buffer);
+double Strtod(Vector<const char> buffer, int exponent) {
+ Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
+ Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);
+ exponent += left_trimmed.length() - trimmed.length();
if (trimmed.length() == 0) return 0.0;
- exponent += buffer.length() - trimmed.length();
+ if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY;
+ if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0;
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
// The trimmed input fits into a double.
// If the 10^exponent (resp. 10^-exponent) fits into a double too then we
diff --git a/src/strtod.h b/src/strtod.h
index 4d256ba..1a5a96c 100644
--- a/src/strtod.h
+++ b/src/strtod.h
@@ -33,7 +33,7 @@
// The buffer must only contain digits in the range [0-9]. It must not
// contain a dot or a sign. It must not start with '0', and must not be empty.
-double Strtod(Vector<char> buffer, int exponent);
+double Strtod(Vector<const char> buffer, int exponent);
} } // namespace v8::internal
diff --git a/src/v8.cc b/src/v8.cc
index 2313967..b30564a 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -68,7 +68,7 @@
OS::Setup();
// Initialize other runtime facilities
-#if !V8_HOST_ARCH_ARM && V8_TARGET_ARCH_ARM
+#if (defined(USE_SIMULATOR) || !V8_HOST_ARCH_ARM) && V8_TARGET_ARCH_ARM
::assembler::arm::Simulator::Initialize();
#endif
diff --git a/src/v8natives.js b/src/v8natives.js
index ca1c99d..88aea9c 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -547,11 +547,11 @@
if (!IS_UNDEFINED(current) && !current.isConfigurable()) {
// Step 5 and 6
- if ((!desc.hasEnumerable() ||
+ if ((!desc.hasEnumerable() ||
SameValue(desc.isEnumerable() && current.isEnumerable())) &&
- (!desc.hasConfigurable() ||
+ (!desc.hasConfigurable() ||
SameValue(desc.isConfigurable(), current.isConfigurable())) &&
- (!desc.hasWritable() ||
+ (!desc.hasWritable() ||
SameValue(desc.isWritable(), current.isWritable())) &&
(!desc.hasValue() ||
SameValue(desc.getValue(), current.getValue())) &&
@@ -755,7 +755,7 @@
var desc = GetOwnProperty(obj, name);
if (desc.isConfigurable()) desc.setConfigurable(false);
DefineOwnProperty(obj, name, desc, true);
- }
+ }
return ObjectPreventExtension(obj);
}
@@ -772,7 +772,7 @@
if (IsDataDescriptor(desc)) desc.setWritable(false);
if (desc.isConfigurable()) desc.setConfigurable(false);
DefineOwnProperty(obj, name, desc, true);
- }
+ }
return ObjectPreventExtension(obj);
}
@@ -1118,12 +1118,12 @@
var bound_args = new $Array(argc_bound);
for(var i = 0; i < argc_bound; i++) {
bound_args[i] = %_Arguments(i+1);
- }
+ }
}
var fn = this;
var result = function() {
// Combine the args we got from the bind call with the args
- // given as argument to the invocation.
+ // given as argument to the invocation.
var argc = %_ArgumentsLength();
var args = new $Array(argc + argc_bound);
// Add bound arguments.
@@ -1132,7 +1132,7 @@
}
// Add arguments from call.
for (var i = 0; i < argc; i++) {
- args[argc_bound + i] = %_Arguments(i);
+ args[argc_bound + i] = %_Arguments(i);
}
// If this is a construct call we use a special runtime method
// to generate the actual object using the bound function.
@@ -1147,7 +1147,7 @@
// try to redefine these as defined by the spec. The spec says
// that bind should make these throw a TypeError if get or set
// is called and make them non-enumerable and non-configurable.
- // To be consistent with our normal functions we leave this as it is.
+ // To be consistent with our normal functions we leave this as it is.
// Set the correct length.
var length = (this.length - argc_bound) > 0 ? this.length - argc_bound : 0;
diff --git a/src/version.cc b/src/version.cc
index 03bf986..33b4977 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -33,8 +33,8 @@
// NOTE these macros are used by the SCons build script so their names
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2
-#define MINOR_VERSION 4
-#define BUILD_NUMBER 9
+#define MINOR_VERSION 5
+#define BUILD_NUMBER 0
#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index b050ec8..d592037 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -1413,20 +1413,8 @@
__ j(equal, &done);
}
__ SmiNeg(rax, rax, &done);
+ __ jmp(&slow); // zero, if not handled above, and Smi::kMinValue.
- // Either zero or Smi::kMinValue, neither of which become a smi when
- // negated. We handle negative zero here if required. We always enter
- // the runtime system if we have Smi::kMinValue.
- if (negative_zero_ == kStrictNegativeZero) {
- __ SmiCompare(rax, Smi::FromInt(0));
- __ j(not_equal, &slow);
- __ Move(rax, Factory::minus_zero_value());
- __ jmp(&done);
- } else {
- __ SmiCompare(rax, Smi::FromInt(Smi::kMinValue));
- __ j(equal, &slow);
- __ jmp(&done);
- }
// Try floating point case.
__ bind(&try_float);
} else if (FLAG_debug_code) {
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index 4ebf44a..7957324 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -584,9 +584,6 @@
void CheckStack();
- static InlineFunctionGenerator FindInlineFunctionGenerator(
- Runtime::FunctionId function_id);
-
bool CheckForInlineRuntimeCall(CallRuntime* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 2256100..32d6242 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -61,6 +61,12 @@
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
+#ifdef DEBUG
+ if (strlen(FLAG_stop_at) > 0 &&
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ __ int3();
+ }
+#endif
__ push(rbp); // Caller's frame pointer.
__ movq(rbp, rsp);
__ push(rsi); // Callee's context.