1
0
Fork 0
mirror of https://github.com/rubyjs/therubyrhino synced 2023-03-27 23:21:34 -04:00

handle Rhino's 64K code generation (method) limit on the fly

simple retry running the failed compilation in interpreter mode
This commit is contained in:
kares 2012-12-05 10:00:41 +01:00
parent 23c617345e
commit 05ece36c5d
2 changed files with 55 additions and 8 deletions

View file

@ -240,24 +240,56 @@ module Rhino
alias :version= :javascript_version= alias :version= :javascript_version=
# Enter this context for operations. # Enter this context for operations.
# Some methods such as eval() will fail unless this context is open ! # Some methods such as eval() will fail unless the context is open.
def open(&block) def open(&block)
do_open(&block) do_open(&block)
rescue JS::RhinoException => e rescue JS::RhinoException => e
if code_generation_error?(e)
warn "[INFO] Rhino byte-code generation failed forcing #{@native} into interpreted mode"
self.optimization_level = -1
retry
end
raise Rhino::JSError.new(e) raise Rhino::JSError.new(e)
end end
private private
def do_open def do_open # :nodoc
factory.enterContext(@native) factory.enterContext(@native)
begin begin
yield self yield self
ensure ensure
factory.exit factory.exit
end
end end
end
CODE_GENERATION_ERROR_MESSAGE = 'generated bytecode for method exceeds 64K limit' # :nodoc
CODE_GENERATION_TRACE_CLASS_NAME = 'org.mozilla.javascript.optimizer.Codegen' # :nodoc
CODE_GENERATION_TRACE_METHOD_NAME = 'reportClassFileFormatException' # :nodoc
# at org.mozilla.javascript.optimizer.Codegen.reportClassFileFormatException
def code_generation_error?(exception) # :nodoc
if ( exception.is_a?(NativeException) rescue nil ) # JRuby 1.6 wrapping
exception = exception.cause
end
if exception.class == Rhino::JS::EvaluatorException
if exception.message.index(CODE_GENERATION_ERROR_MESSAGE)
return true
end
# NOTE: unfortunately Rhino localizes the error messages!
# and the ClassFileFormatException is not kept as a cause
class_name = CODE_GENERATION_TRACE_CLASS_NAME
method_name = CODE_GENERATION_TRACE_METHOD_NAME
for trace in exception.getStackTrace()
if class_name == trace.class_name && method_name == trace.method_name
return true
end
end
end
false
end
end end
class IOReader < java.io.Reader # :nodoc: class IOReader < java.io.Reader # :nodoc:

View file

@ -166,4 +166,19 @@ describe Rhino::Context do
end end
end end
it "handles code generation error when 'generated bytecode for method exceeds 64K limit'" do
context = Rhino::Context.new
big_script = ''
10000.times { |i| big_script << "var s#{i} = '#{i}';\n" }
10000.times { |i| big_script << "var n#{i} = +#{i} ;\n" }
lambda {
context.eval big_script
}.should_not raise_error
context.eval('( s9999 )').should == '9999'
context.eval('( n9999 )').should == +9999
end
end end