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(); |
} |