Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Unified Diff: src/liveedit.cc

Issue 7080029: Fix Issue 1320: LiveEdit: text differencer fails with out of memory on large files (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: merge Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/liveedit.h ('k') | src/liveedit-debugger.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/liveedit.cc
diff --git a/src/liveedit.cc b/src/liveedit.cc
index e89cae3ac95fbde6230423ae6efec21181826338..5c585741345ed2cbd025a5b5b2c87fc4149c4a7a 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -59,18 +59,64 @@ void SetElementNonStrict(Handle<JSObject> object,
USE(no_failure);
}
+// Creates string expression and throws it in V8 isolate.
+void ThrowStringException(const char* str, Isolate* isolate) {
+ Vector<const char> str_vector(str, strlen(str));
+ MaybeObject* maybe_exception =
+ isolate->heap()->AllocateStringFromAscii(str_vector);
+ Object* exception;
+ if (maybe_exception->ToObject(&exception)) {
+ isolate->Throw(exception, NULL);
+ }
+}
+
// A simple implementation of dynamic programming algorithm. It solves
-// the problem of finding the difference of 2 arrays. It uses a table of results
-// of subproblems. Each cell contains a number together with 2-bit flag
+// the problem of finding the difference of 2 arrays. It uses a table of
+// results of subproblems. Each cell contains a number together with 2-bit flag
// that helps building the chunk list.
class Differencer {
public:
- explicit Differencer(Comparator::Input* input)
- : input_(input), len1_(input->getLength1()), len2_(input->getLength2()) {
- buffer_ = NewArray<int>(len1_ * len2_);
+ explicit Differencer(Comparator::Input* input, Isolate* isolate,
+ bool* has_exception)
+ : input_(input), buffer_(NULL), len1_(input->getLength1()),
+ len2_(input->getLength2()) {
+ // Put multiply result into a bigger integer.
+ int64_t multiply =
+ static_cast<int64_t>(len1_) * static_cast<int64_t>(len2_);
+
+ // Maximum table size is max_int. Within this limit it's easy to check
+ // for multiply overflow. Should we support bigger numbers?
+ if (multiply > kMaxInt) {
+ ThrowStringException("Too many lines: differencer table size is too big",
+ isolate);
+ *has_exception = true;
+ return;
+ }
+ multiply *= sizeof(int); // NOLINT
+ size_t size = multiply;
+ if (size != multiply) {
+ // Shouldn't be reachable.
+ ThrowStringException(
+ "Too many lines: "
+ "differencer table buffer size doesn't fit into size_t", isolate);
+ *has_exception = true;
+ return;
+ }
+ void* p = malloc(size);
+ if (p == NULL) {
+ ThrowStringException(
+ "Too many lines: not enough memory for differencer table buffer",
+ isolate);
+ *has_exception = true;
+ return;
+ }
+ buffer_ = reinterpret_cast<int*>(p);
}
+
~Differencer() {
- DeleteArray(buffer_);
+ if (buffer_ != NULL) {
+ free(buffer_);
+ }
}
void Initialize() {
@@ -259,12 +305,18 @@ class Differencer {
};
-void Comparator::CalculateDifference(Comparator::Input* input,
- Comparator::Output* result_writer) {
- Differencer differencer(input);
+MUST_USE_RESULT MaybeObject/*<void>*/* Comparator::CalculateDifference(
+ Comparator::Input* input, Comparator::Output* result_writer,
+ Isolate* isolate) {
+ bool has_exception = false;
+ Differencer differencer(input, isolate, &has_exception);
+ if (has_exception) {
+ return Failure::Exception();
+ }
differencer.Initialize();
differencer.FillTable();
differencer.SaveResult(result_writer);
+ return Smi::FromInt(0); // Unused value.
}
@@ -442,8 +494,10 @@ class TokenizingLineArrayCompareOutput : public Comparator::Output {
public:
TokenizingLineArrayCompareOutput(LineEndsWrapper line_ends1,
LineEndsWrapper line_ends2,
- Handle<String> s1, Handle<String> s2)
- : line_ends1_(line_ends1), line_ends2_(line_ends2), s1_(s1), s2_(s2) {
+ Handle<String> s1, Handle<String> s2,
+ Isolate* isolate)
+ : line_ends1_(line_ends1), line_ends2_(line_ends2), s1_(s1), s2_(s2),
+ isolate_(isolate) {
}
void AddChunk(int line_pos1, int line_pos2, int line_len1, int line_len2) {
@@ -461,7 +515,12 @@ class TokenizingLineArrayCompareOutput : public Comparator::Output {
TokensCompareOutput tokens_output(&array_writer_, char_pos1,
char_pos2);
- Comparator::CalculateDifference(&tokens_input, &tokens_output);
+ MaybeObject* res = Comparator::CalculateDifference(&tokens_input,
Søren Thygesen Gjesse 2011/05/31 08:03:09 All arguments on same line or each argument on sep
+ &tokens_output, isolate_);
+ if (res->IsFailure()) {
+ // We asked for a small amount of memory, this should not happen.
+ UNREACHABLE();
+ }
} else {
array_writer_.WriteChunk(char_pos1, char_pos2, char_len1, char_len2);
}
@@ -479,11 +538,14 @@ class TokenizingLineArrayCompareOutput : public Comparator::Output {
LineEndsWrapper line_ends2_;
Handle<String> s1_;
Handle<String> s2_;
+ Isolate* isolate_;
};
-Handle<JSArray> LiveEdit::CompareStrings(Handle<String> s1,
- Handle<String> s2) {
+MUST_USE_RESULT MaybeObject/*<JSArray>*/* LiveEdit::CompareStrings(
+ Handle<String> s1, Handle<String> s2) {
+
+ Isolate* isolate = Isolate::Current();
s1 = FlattenGetString(s1);
s2 = FlattenGetString(s2);
@@ -491,11 +553,16 @@ Handle<JSArray> LiveEdit::CompareStrings(Handle<String> s1,
LineEndsWrapper line_ends2(s2);
LineArrayCompareInput input(s1, s2, line_ends1, line_ends2);
- TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2);
+ TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2,
Søren Thygesen Gjesse 2011/05/31 08:03:09 All arguments on same line or each argument on sep
+ isolate);
- Comparator::CalculateDifference(&input, &output);
+ MaybeObject* result = Comparator::CalculateDifference(&input, &output,
Søren Thygesen Gjesse 2011/05/31 08:03:09 All arguments on same line or each argument on sep
+ isolate);
+ if (result->IsFailure()) {
+ return result;
+ }
- return output.GetResult();
+ return *output.GetResult();
}
« no previous file with comments | « src/liveedit.h ('k') | src/liveedit-debugger.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698