diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 61ed85f..63c4469 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -647,7 +647,7 @@ int rb_reg_options(VALUE);
 #define rb_argv rb_get_argv()
 RUBY_EXTERN VALUE rb_argv0;
 VALUE rb_get_argv(void);
-void *rb_load_file(const char*);
+void *rb_load_file(VALUE, const char*);
 void ruby_script(const char*);
 void ruby_prog_init(void);
 void ruby_set_argv(int, char**);
diff --git a/internal.h b/internal.h
index e581842..35332b1 100644
--- a/internal.h
+++ b/internal.h
@@ -114,6 +114,7 @@ void rb_stdio_set_default_encoding(void);
 /* iseq.c */
 VALUE rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE filepath, VALUE line, VALUE opt);
 VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase);
+void rb_compile_option_set(VALUE opt);
 
 /* load.c */
 VALUE rb_get_load_path(void);
@@ -144,6 +145,7 @@ VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
 /* parse.y */
 VALUE rb_parser_get_yydebug(VALUE);
 VALUE rb_parser_set_yydebug(VALUE, VALUE);
+VALUE rb_parser_compile_option(VALUE);
 int rb_is_const_name(VALUE name);
 int rb_is_class_name(VALUE name);
 int rb_is_global_name(VALUE name);
diff --git a/iseq.c b/iseq.c
index ec9ac5f..73cf8fa 100644
--- a/iseq.c
+++ b/iseq.c
@@ -383,10 +383,14 @@ rb_iseq_new(NODE *node, VALUE name, VALUE filename, VALUE filepath,
 }
 
 VALUE
-rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent)
+rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath,
+		VALUE parent, VALUE compile_option)
 {
-    return rb_iseq_new_with_opt(node, name, filename, filepath, INT2FIX(0), parent, ISEQ_TYPE_TOP,
-				&COMPILE_OPTION_DEFAULT);
+    rb_compile_option_t option;
+
+    make_compile_option(&option, compile_option);
+    return rb_iseq_new_with_opt(node, name, filename, filepath, INT2FIX(0),
+				parent, ISEQ_TYPE_TOP, &option);
 }
 
 VALUE
@@ -625,6 +629,12 @@ iseq_s_compile_option_set(VALUE self, VALUE opt)
     return opt;
 }
 
+void
+rb_compile_option_set(VALUE opt)
+{
+    iseq_s_compile_option_set(Qnil, opt);
+}
+
 static VALUE
 iseq_s_compile_option_get(VALUE self)
 {
diff --git a/load.c b/load.c
index 26d8568..545f140 100644
--- a/load.c
+++ b/load.c
@@ -300,12 +300,15 @@ rb_load_internal(VALUE fname, int wrap)
     state = EXEC_TAG();
     if (state == 0) {
 	NODE *node;
-	VALUE iseq;
+	VALUE parser, iseq;
 
 	th->mild_compile_error++;
-	node = (NODE *)rb_load_file(RSTRING_PTR(fname));
+	parser = rb_parser_new();
+	node = (NODE *)rb_load_file(parser, RSTRING_PTR(fname));
 	loaded = TRUE;
-	iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), Qfalse);
+	iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"),
+			       fname, rb_realpath_internal(Qnil, fname, 1),
+			       Qfalse, rb_parser_compile_option(parser));
 	th->mild_compile_error--;
 	rb_iseq_eval(iseq);
     }
diff --git a/parse.y b/parse.y
index 0393dc1..5a83e46 100644
--- a/parse.y
+++ b/parse.y
@@ -238,6 +238,7 @@ struct parser_params {
     int parser_ruby_sourceline;	/* current line no. */
     rb_encoding *enc;
     rb_encoding *utf8;
+    VALUE compile_option;
 
     int parser_yydebug;
 
@@ -6518,6 +6519,38 @@ parser_set_token_info(struct parser_params *parser, const char *name, const char
     rb_compile_warning(ruby_sourcefile, ruby_sourceline, "invalid value for %s: %s", name, val);
 }
 
+static void
+parser_set_compile_option(struct parser_params *parser,
+			  const char *name, const char *val)
+{
+    switch (*val) {
+      case 't': case 'T':
+	if (strcasecmp(val, "true") == 0) {
+	    rb_hash_aset(parser->compile_option, ID2SYM(rb_intern(name)),
+			 Qtrue);
+	    return;
+	}
+	break;
+      case 'f': case 'F':
+	if (strcasecmp(val, "false") == 0) {
+	    rb_hash_aset(parser->compile_option, ID2SYM(rb_intern(name)),
+			 Qfalse);
+	    return;
+	}
+	break;
+    }
+    rb_compile_warning(ruby_sourcefile, ruby_sourceline,
+		       "invalid value for %s: %s", name, val);
+}
+
+static void
+parser_set_compile_option_num(struct parser_params *parser,
+			      const char *name, const char *val)
+{
+    rb_hash_aset(parser->compile_option, ID2SYM(rb_intern(name)),
+		 rb_cstr_to_inum(val, 10, 0));
+}
+
 struct magic_comment {
     const char *name;
     rb_magic_comment_setter_t func;
@@ -6528,6 +6561,15 @@ static const struct magic_comment magic_comments[] = {
     {"coding", magic_comment_encoding, parser_encode_length},
     {"encoding", magic_comment_encoding, parser_encode_length},
     {"warn_indent", parser_set_token_info},
+    {"inline_const_cache", parser_set_compile_option},
+    {"peephole_optimization", parser_set_compile_option},
+    {"tailcall_optimization", parser_set_compile_option},
+    {"specialized_instruction", parser_set_compile_option},
+    {"operands_unification", parser_set_compile_option},
+    {"instructions_unification", parser_set_compile_option},
+    {"stack_caching", parser_set_compile_option},
+    {"trace_instruction", parser_set_compile_option},
+    {"debug_level", parser_set_compile_option_num},
 };
 #endif
 
@@ -10407,6 +10449,7 @@ parser_initialize(struct parser_params *parser)
     parser->parser_lvtbl = 0;
     parser->parser_ruby__end__seen = 0;
     parser->parser_ruby_sourcefile = 0;
+    parser->compile_option = rb_hash_new();
 #ifndef RIPPER
     parser->is_ripper = 0;
     parser->parser_eval_tree_begin = 0;
@@ -10441,6 +10484,7 @@ parser_mark(void *ptr)
     rb_gc_mark(p->parser_lex_input);
     rb_gc_mark(p->parser_lex_lastline);
     rb_gc_mark(p->parser_lex_nextline);
+    rb_gc_mark(p->compile_option);
 #ifndef RIPPER
     rb_gc_mark((VALUE)p->parser_eval_tree_begin) ;
     rb_gc_mark((VALUE)p->parser_eval_tree) ;
@@ -10600,6 +10644,16 @@ rb_parser_set_yydebug(VALUE self, VALUE flag)
     return flag;
 }
 
+VALUE
+rb_parser_compile_option(VALUE self)
+{
+    struct parser_params *parser;
+
+    TypedData_Get_Struct(self, struct parser_params, &parser_data_type,
+			 parser);
+    return parser->compile_option;
+}
+
 #ifdef YYMALLOC
 #define HEAPCNT(n, size) ((n) * (size) / sizeof(YYSTYPE))
 #define NEWHEAP() rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0)
diff --git a/ruby.c b/ruby.c
index d6f0432..86ddb52 100644
--- a/ruby.c
+++ b/ruby.c
@@ -1405,6 +1405,7 @@ process_options(int argc, char **argv, struct cmdline_options *opt)
 	    tree = load_file(parser, opt->script_name, 1, opt);
 	});
     }
+    rb_compile_option_set(rb_parser_compile_option(parser));
     rb_progname = opt->script_name;
     rb_vm_set_progname(rb_progname);
     if (opt->dump & DUMP_BIT(yydebug)) return Qtrue;
@@ -1677,12 +1678,12 @@ load_file(VALUE parser, VALUE fname, int script, struct cmdline_options *opt)
 }
 
 void *
-rb_load_file(const char *fname)
+rb_load_file(VALUE parser, const char *fname)
 {
     struct cmdline_options opt;
     VALUE fname_v = rb_str_new_cstr(fname);
 
-    return load_file(rb_parser_new(), fname_v, 0, cmdline_options_init(&opt));
+    return load_file(parser, fname_v, 0, cmdline_options_init(&opt));
 }
 
 static void
diff --git a/vm_core.h b/vm_core.h
index a835e23..a936a3c 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -501,7 +501,7 @@ typedef struct rb_thread_struct {
 #pragma GCC visibility push(default)
 #endif
 VALUE rb_iseq_new(NODE*, VALUE, VALUE, VALUE, VALUE, enum iseq_type);
-VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent);
+VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent, VALUE compile_option);
 VALUE rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath);
 VALUE rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, enum iseq_type, VALUE);
 VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, enum iseq_type, const rb_compile_option_t*);
